IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Delphi Discussion :

Fichier CSV en XML


Sujet :

Delphi

  1. #1
    Membre confirmé Avatar de cantador
    Homme Profil pro
    Chef de projet
    Inscrit en
    Mars 2006
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Aude (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Chef de projet
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Mars 2006
    Messages : 569
    Points : 484
    Points
    484
    Par défaut Fichier CSV en XML
    Bonjour,

    je reprends la discussion entamée sur "structurer un fichier texte"..
    après avoir cherché, j'ai opté pour la solution proposée par SergioMaster.

    j'ai désormais transformé mon fichier .csv (provenant d'un pdf parsé..) en une structure XML dont je vous joins un extrait significatif
    puisque tous les cas de figure y sont représentés :

    Nom : Capture.PNG
Affichages : 346
Taille : 47,7 Ko

    Maintenant, il faudrait pouvoir la lire, sachant que x "titre intitulé" contenant y "Section nom" renfermant z Ligne

    il est nécessaire de lire tout le fichier :
    lire les lignes contenant le mot accord et récupérer uniquement la date la plus récente figurant en bout de ligne.
    idem avec le mot SUPER

    Donc, en résumé pour chaque "titre intitulé", il faut récupérer :

    - le titre intitulé
    - la section nom
    - si présence accord->> le mot accord et sa date la plus récente
    - si présence SUPER seule ->> le mot SUPER et sa date la plus récente

    il y a toutefois deux exceptions :
    - des "titre intitulé" VIDE (sans aucune section)
    - des "Section nom" qui ne contiennent ni le mot accord ni le mot super

    ces deux cas là devront être récupérés en :
    - le titre intitulé
    et
    - le mot NEANT

    ça devrait être plus clair..
    et le nec serait de mettre les résultats sous forme d'un .csv permettant de passer en mode tableau

    merci pour le coup de main car je débute en XML (c'est malin, je vais même finir par y prendre goût à cause sergiomaster...)

    cordialement

  2. #2
    Membre confirmé Avatar de cantador
    Homme Profil pro
    Chef de projet
    Inscrit en
    Mars 2006
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Aude (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Chef de projet
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Mars 2006
    Messages : 569
    Points : 484
    Points
    484
    Par défaut précision
    un petit oubli..

    des "Section nom" qui ne contiennent ni le mot accord ni le mot SUPER
    devront être récupérées avec la mention VIDE
    et ce n'est que si l'intitulé n'a pas de section ou
    que l'ensemble des sections qui y sont contenues sont classées VIDE que la mention NEANT devra apparaître

    un peu tordu quand même..
    mais c'est exactement ce dont j'ai besoin
    @+

  3. #3
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 430
    Points
    28 430
    Par défaut
    il y a quelque chose qui m'échappe....

    pourquoi passer de CSV à XML si c'est pour ensuite chercher à traiter le XML ?!

    pourquoi ne pas simplement charger le fichier CSV dans une arborescence en mémoire et la traiter directement ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    var
      TSection = record
        Texte: string;
        Lignes: array of string; // ou TStringList
      end,
     
      TTitre = record
        Texte: string;
        Sections: array of TSection;
      end;
      TStructure = array of TTitre;
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  4. #4
    Membre confirmé Avatar de cantador
    Homme Profil pro
    Chef de projet
    Inscrit en
    Mars 2006
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Aude (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Chef de projet
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Mars 2006
    Messages : 569
    Points : 484
    Points
    484
    Par défaut arborescence
    Bonsoir Paul Toth,

    je l'ai fait avec un TBLOC: array of TStringList;
    mais à terme, ça devient très compliqué..
    mais peut-être que je m'y suis mal pris ?

    Attention quand je dis csv, en fait il n'y a que les dates qui sont derrière des point-virgule !
    le fichier de départ a plutôt cette tête là :

    intitulé
    section
    ligne;date
    intitulé
    section
    ligne; date
    etc.

    et j'ai besoin aussi d'avoir un visuel de l'arborescence car cela me permettra d'identifier rapidement les éventuelles modifications du fichier
    qui pourraient apparaître avec le temps, car dans cet exercice, je ne maîtrise pas du tout la source.

    j'ai pensé qu'une bonne structure XML m'aiderait dans ma quête...

    mais, avec tous les éléments que j'ai fournis, pourrais-tu préciser un peu mieux ton idée et me donner un début de traitement ?

    ici, il fait une canicule épouvantable.

    merci par avance

    cordialement

  5. #5
    Membre confirmé
    Avatar de alheuredudejeuner
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2005
    Messages
    376
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2005
    Messages : 376
    Points : 632
    Points
    632
    Billets dans le blog
    4
    Par défaut Un truc m'echappe
    Bonjour

    Pourquoi faire un noeud
    <ligne>Accord madate; blabla</ligne>
    et ne pas faire
    <Accord>madate; blabla</Accord>
    Cordialement

    Pour lire un fichier xml j'utilise XML Notepad.

  6. #6
    Membre confirmé Avatar de cantador
    Homme Profil pro
    Chef de projet
    Inscrit en
    Mars 2006
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Aude (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Chef de projet
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Mars 2006
    Messages : 569
    Points : 484
    Points
    484
    Par défaut noeud
    Bonjour à tous,

    Oui, j'ai vu ce truc, c'est juste à cause du traitement du parser en amont.
    et je n'ai pas envie de m'embêter à retirer les dates en trop car elles ne me gênent pas.. (@alheuredudejeuner)

    une première idée me vient pour la suite est de faire une première passe
    en mettant un attribut au bloc section nom : qui prendrait donc trois valeurs possibles:

    - COMPLET ->>>> si il y au moins le (mot accord seul) ou (accord et SUPER)
    - SUPER ->>>> si SUPER est tout seul
    - VIDE ->>>> si accord et super sont absents

    sans chercher les dates les plus récentes qui feront l'objet d'un second traitement.

    Donc, je reformule autrement :

    Comment faire pour lire, toutes les sections et leur affecter un attribut en fonction de la présence des mots désignés précédemment dans les lignes constituant le bloc ?
    et
    y-a t-il des méthodes XML qui permettent de chercher une chaine dans les lignes des sections ?

    merci pour votre aide

    cordialement

  7. #7
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    Dommage que votre fichier XML soit une image donc non récupérable... Je crois que j'étais intervenu dans la première discussion. Je suis toujours persuadé qu'avec des RegEx, on peut résoudre ce problème. Je connais celles de Lazarus, Qt et Windev... et pas trop celle(s) de Delphi. Justement ce serait une bonne occasion de découvrir la nouvelle XE RegularExpressions unit (la "native" intégrée à Delphi XE, celle qui est décrite au milieu de la page) car il est vrai que d'une librairie à l'autre, les différences sont souvent "marquées"... En vacances (sauf demain et après demain en stage) , j'aimerais tester... J'ai un petit peu de temps. Vous ne pourriez pas le zipper votre XML ?

    ADDENDUM 20H45 : Bon, j'ai regardé rapidement (en FMX). La System.RegularExpressions me semble* suffisamment complète pour extraire les données. Lazy et Greedy semblent opérationnels.
    * Il faut vérifier avec des expressions plus élaborées.

    Un test simple et évidemment incomplet montre comment on peut extraire les données :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    procedure TForm1.Button1Click(Sender: TObject);
      {System.RegularExpressions}
      function ExtractBetweenTags(const s : string; FirstTag, LastTag : string) : string;
      var
        aRegEx    : TRegEx;
        aMatch    : TMatch;
        aMatches  : TMatchCollection;
      begin
        aRegEx := TRegEx.Create(Format('(?si)%s(.*?)%s', [FirstTag, LastTag]));
        aMatches := aRegEx.Matches(s);
        for aMatch in aMatches do
          ShowMessage(Format('%s (%d, %d)',[aMatch.Value, aMatch.Index, aMatch.Length]));
      end;
     
    var
      s : string;
    begin
      s :='<CATALOG>' + sLineBreak +
          '<CD nom="CD1">' + sLineBreak +
          '<TITLE>Empire Burlesque</TITLE>' + sLineBreak +
          '<ARTIST>Bob Dylan</ARTIST>' + sLineBreak +
          '<COUNTRY>USA</COUNTRY>' + sLineBreak +
          '<COMPANY>Columbia</COMPANY>' + sLineBreak +
          '<PRICE>10.90</PRICE>' + sLineBreak +
          '<YEAR>1985</YEAR>' + sLineBreak +
          '</CD>' + sLineBreak +
          '<CD nom="CD2"> ' + sLineBreak +
          '<TITLE>Hide your heart</TITLE>' + sLineBreak +
          '<ARTIST>Bonnie Tyler</ARTIST>' + sLineBreak +
          '<COUNTRY>UK</COUNTRY>' + sLineBreak +
          '<COMPANY>CBS Records</COMPANY>' + sLineBreak +
          '<PRICE>9.90</PRICE>' + sLineBreak +
          '<YEAR>1988</YEAR>' + sLineBreak +
          '</CD>' + sLineBreak +
          '<CD nom="CD3">' + sLineBreak +
          '<TITLE>Greatest Hits</TITLE>' + sLineBreak +
          '<ARTIST>Dolly Parton</ARTIST>' + sLineBreak +
          '<COUNTRY>USA</COUNTRY>' + sLineBreak +
          '<COMPANY>RCA</COMPANY>' + sLineBreak +
          '<PRICE>9.90</PRICE>' + sLineBreak +
          '<YEAR>1982</YEAR>' + sLineBreak +
          '</CD>' + sLineBreak +
          '<CD nom="CD4">' + sLineBreak +
          '<TITLE>Still got the blues</TITLE>' + sLineBreak +
          '<ARTIST>Gary Moore</ARTIST>' + sLineBreak +
          '<COUNTRY>UK</COUNTRY>' + sLineBreak +
          '<COMPANY>Virgin records</COMPANY>' + sLineBreak +
          '<PRICE>10.20</PRICE>' + sLineBreak +
          '<YEAR>1990</YEAR>' + sLineBreak +
          '</CD>' + sLineBreak +
          '</CATALOG>';
      ExtractBetweenTags(s,'<CD nom=','</CD>');
    end;
    On peut se débarrasser des tags et même de <Section nom= "blabla..;"> quelque soit blabla.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    procedure TForm1.Button2Click(Sender: TObject);
     {System.RegularExpressions}
      function ExtractBetweenTags(const s : string; FirstTag, LastTag : string) : string;
      var
        aRegEx    : TRegEx;
        aMatch    : TMatch;
        aMatches  : TMatchCollection;
      begin
        aRegEx := TRegEx.Create(Format('(?si)%s.*?>(.*?)%s', [FirstTag, LastTag]));
        aMatches := aRegEx.Matches(s);
        for aMatch in aMatches do
          ShowMessage(Format('%s (%d, %d)',[aMatch.Groups[1].Value, aMatch.Index, aMatch.Length]));
      end;
     
    var
      s : string;
    begin
      s :='<CATALOG>' + sLineBreak +
          '<CD nom="CD1">' + sLineBreak +
          '<TITLE>Empire Burlesque</TITLE>' + sLineBreak +
          '<ARTIST>Bob Dylan</ARTIST>' + sLineBreak +
          '<COUNTRY>USA</COUNTRY>' + sLineBreak +
          '<COMPANY>Columbia</COMPANY>' + sLineBreak +
          '<PRICE>10.90</PRICE>' + sLineBreak +
          '<YEAR>1985</YEAR>' + sLineBreak +
          '</CD>' + sLineBreak +
          '<CD nom="CD2"> ' + sLineBreak +
          '<TITLE>Hide your heart</TITLE>' + sLineBreak +
          '<ARTIST>Bonnie Tyler</ARTIST>' + sLineBreak +
          '<COUNTRY>UK</COUNTRY>' + sLineBreak +
          '<COMPANY>CBS Records</COMPANY>' + sLineBreak +
          '<PRICE>9.90</PRICE>' + sLineBreak +
          '<YEAR>1988</YEAR>' + sLineBreak +
          '</CD>' + sLineBreak +
          '<CD nom="CD3">' + sLineBreak +
          '<TITLE>Greatest Hits</TITLE>' + sLineBreak +
          '<ARTIST>Dolly Parton</ARTIST>' + sLineBreak +
          '<COUNTRY>USA</COUNTRY>' + sLineBreak +
          '<COMPANY>RCA</COMPANY>' + sLineBreak +
          '<PRICE>9.90</PRICE>' + sLineBreak +
          '<YEAR>1982</YEAR>' + sLineBreak +
          '</CD>' + sLineBreak +
          '<CD nom="CD4">' + sLineBreak +
          '<TITLE>Still got the blues</TITLE>' + sLineBreak +
          '<ARTIST>Gary Moore</ARTIST>' + sLineBreak +
          '<COUNTRY>UK</COUNTRY>' + sLineBreak +
          '<COMPANY>Virgin records</COMPANY>' + sLineBreak +
          '<PRICE>10.20</PRICE>' + sLineBreak +
          '<YEAR>1990</YEAR>' + sLineBreak +
          '</CD>' + sLineBreak +
          '</CATALOG>';
      ExtractBetweenTags(s,'<CD nom=','</CD>');
    end;
    Ainsi vous pouvez récupérer n'importe quelle valeur de balise simple. Ci-joint un zip du projet de test (XE7).
    Fichiers attachés Fichiers attachés
    Dernière modification par Invité ; 08/07/2015 à 23h00.

  8. #8
    Membre confirmé Avatar de cantador
    Homme Profil pro
    Chef de projet
    Inscrit en
    Mars 2006
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Aude (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Chef de projet
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Mars 2006
    Messages : 569
    Points : 484
    Points
    484
    Par défaut RegEx
    Bonjour selzig,
    merci pour cette idée de formatage
    mais je suis sous D7..
    @+

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2010
    Messages
    71
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 71
    Points : 102
    Points
    102
    Par défaut
    Salut Cantador,

    voici peut-être un point de départ à adapter
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    procedure TForm1.Button1Click(Sender: TObject);
    var
      Node    : IXMLNode;
      I       : Integer;
      Titre   : IXMLNode;
      Section : IXMLNode;
      Ligne   : IXMLNode;
      List    : TStringList;
      Accord  : Boolean;
      Super   : Boolean;
      TiTemp  : string;
      DateAcc : string;
      DateSup : string;
      DateAcD : array of TDate;
      Fichier : TStringList;
    begin
      XMLDocument1.LoadFromFile(ExtractFilePath(Application.ExeName)+'Fichier.xml');
      Node := XMLDocument1.ChildNodes.Nodes['XML'];
      Titre := Node.ChildNodes.Nodes['Titre'];
      Fichier := TStringList.Create;
      try
        while Titre <> nil do
        begin
          if Titre.GetAttributeNS('intitulé','') <> '' then
            TiTemp := Titre.GetAttributeNS('intitulé','')
          else
            Fichier.Add('Vide pas d''intitulé;;;;VIDE');
          if Titre.HasChildNodes then
          begin
            Accord := False;
            Super := False;
            DateAcc := '';
            DateSup := '';
            Section := Titre.ChildNodes.Nodes['Section'];
            while Section <> nil do
            begin
              if Section.HasChildNodes then
              begin
                Ligne := Section.ChildNodes.Nodes['Lignes'].ChildNodes.Nodes['Ligne'];
                while Ligne <> nil do
                begin
                  List := TStringList.Create;
                  List.Delimiter := ';';
                  List.DelimitedText := Ligne.NodeValue;
                  try
                    for I := 0 to List.Count - 1 do
                    begin
                      if I = 0 then
                      begin
                        if List[I]='accord' then
                        begin
                          Accord := True;
                          DateAcc := List[2];
                          SetLength(DateAcD,Length(DateAcD)+1);
                          DateAcD[Length(DateAcD)-1] := StrTodate(List[2]);
                        end;
                        if List[I]='SUPER' then
                        begin
                          Super := True;
                          DateSup := List[2];
                        end;
                      end;
                    end;
                    Ligne := Ligne.NextSibling;
                  finally
                    List.Free;
                  end;
                end;
                if Titre.GetAttributeNS('intitulé','') <> '' then
                begin
                  if not Accord and not Super then
                    Fichier.Add(TiTemp+Section.GetAttributeNS('nom','')+';;VIDE');
                  {if Accord and not Super then
                    Fichier.Add(TiTemp+Section.GetAttributeNS('nom','')+';'+DateAcc+';ACCORD');
                  if Accord and Super then
                      Fichier.Add(TiTemp+Section.GetAttributeNS('nom','')+DateSup+';'+DateAcc+';SUPER ACCORD');}
                  if Accord and not Super then
                    for I := 0 to Length(DateAcD)-1 do
                      Fichier.Add(TiTemp+Section.GetAttributeNS('nom','')+';'+DateToStr(DateAcD[I])+';ACCORD');
                  if not Accord and Super then
                    Fichier.Add(TiTemp+Section.GetAttributeNS('nom','')+DateSup+';;SUPER');
                  if Accord and Super then
                    for I := 0 to Length(DateAcD)-1 do
                      Fichier.Add(TiTemp+Section.GetAttributeNS('nom','')+DateSup+';'+DateToStr(DateAcD[I])+';SUPER ACCORD');
                  SetLength(DateAcD,0);
                end;
                Section := Section.NextSibling;
              end
              else
                Fichier.Add(TiTemp+'Section vide;;;VIDE');
            end;
          end
          else
            if Titre.GetAttributeNS('intitulé','') <> '' then
              Fichier.Add(TiTemp+'Pas de section;;;VIDE');
          Titre := Titre.NextSibling;
        end;
        Fichier.SaveToFile(ExtractFilePath(Application.ExeName)+'Resultat.csv');
      finally
        Fichier.Free;
        FreeMemory(DateAcD);
      end;
    end;
    @+

  10. #10
    Membre confirmé Avatar de cantador
    Homme Profil pro
    Chef de projet
    Inscrit en
    Mars 2006
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Aude (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Chef de projet
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Mars 2006
    Messages : 569
    Points : 484
    Points
    484
    Par défaut merci nuxtay
    Bonjour,

    j'ai testé toutes les idées proposées y compris celle de Paul TOTH.
    Bon, j'ai fait un petit break de vacances.
    raté, maintenant, j'ai plusieurs projets en même temps..
    pour le traitement du fichier csv
    j'hésite entre les TRecord (Toth) et XML..

    je vais étudier ta solution.
    j''ai une autre question à poser (rien à voir avec ce programme..)

    en tout cas merci pour l'aide

    @+

Discussions similaires

  1. Réponses: 0
    Dernier message: 27/06/2012, 16h00
  2. parser fichier xml vers fichier csv
    Par kemeticShamman dans le forum Général Python
    Réponses: 1
    Dernier message: 10/01/2012, 17h45
  3. Export fichier format autre que CSV et XML
    Par dbaenbois dans le forum Développement de jobs
    Réponses: 2
    Dernier message: 21/07/2009, 21h45
  4. [XML] Passer un fichier CSV en un fichier XML
    Par stardeus dans le forum APIs
    Réponses: 3
    Dernier message: 14/03/2007, 17h01
  5. [XML] convertir fichier CSV en XML
    Par Yudala dans le forum XML/XSL et SOAP
    Réponses: 1
    Dernier message: 16/02/2007, 10h05

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo