1. #1
    Membre actif Avatar de franckcl
    Homme Profil pro
    Developpeur Delphi
    Inscrit en
    septembre 2004
    Messages
    286
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Developpeur Delphi
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : septembre 2004
    Messages : 286
    Points : 213
    Points
    213

    Par défaut XML: comment décoder le string "<MSG><CR><LF>"

    Bonjour,

    J'ai un fichier xml qui ressemble à ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    <xml>
      <regulator>
        <protocol readformat="&lt;MSG&gt;&lt;CR&gt;&lt;LF&gt;"/>
      </regulator>
    </xml>
    Dans lequel, la chaine readformat est codé et contient en réalité : "<MSG><CR><LF>"
    J'ai besoin de récupérer cette chaine sans passer par les fonctions XML (pour accélérer le traitement).
    Quel codage s'agit-il ? Comment décoder cette chaine ? Existe-t-il une fonction de décodage ?
    merci
    Franck

  2. #2
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique
    Inscrit en
    janvier 2007
    Messages
    8 229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : janvier 2007
    Messages : 8 229
    Points : 18 867
    Points
    18 867
    Billets dans le blog
    4

    Par défaut

    Bonjour,

    si le XML n'a que ça, j'utiliserai quelques ReplaceStr pour les &lt; et &gt;
    et un copy pour extraire avec un pos de '="' pour le début et de pos '"/>' pour la fin
    La seule chose absolue dans un monde comme le nôtre, c'est l'humour. » Albert Einstein
    J'entends et j'oublie. Je vois et je me souviens. Je fais et je comprends . Confucius
    Si votre seul outil est un marteau, vous aurez tendance a ne voir que des clous

  3. #3
    Membre actif Avatar de franckcl
    Homme Profil pro
    Developpeur Delphi
    Inscrit en
    septembre 2004
    Messages
    286
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Developpeur Delphi
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : septembre 2004
    Messages : 286
    Points : 213
    Points
    213

    Par défaut

    Merci Sergio mais ce que j'ai donné n'est qu'un exemple, je ne connais pas tous les caractères à transformer et surtout je risque d'en louper et d'en découvrir d'autres au fil de temps, ce que je ne veux pas.
    TXMLDocument fait la conversion (ou plutot IXMLNode.GetAttributeNS(item, '')) mais je n'arrive pas à trouver la fonction qui est utilisée pour faire ça.


    merci

  4. #4
    Membre averti Avatar de Cirec
    Profil pro
    Inscrit en
    octobre 2010
    Messages
    183
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : octobre 2010
    Messages : 183
    Points : 389
    Points
    389

    Par défaut

    Bonjour,

    la fonction que tu cherche fait partie d'une Interface
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
      IDOMElement = interface(IDOMNode)
        ['{2BF4C0E6-096E-11D4-83DA-00C04F60B2DD}']
     ...
        function getAttributeNS(const namespaceURI, localName: DOMString): DOMString; safecall;    { DOM Level 2 }
    et du coup, si tu penses découvrir d'autres caractères il est préférable d'utiliser "getAttributeNS" qui adaptera la conversion au contenu
    dépendant de l'encodage utilisé (Latain, Cyrillic, Grec, Math, ...) XML Character Entities

    faire sa propre routine ne serait pas forcément plus rapide.

    enfin ce n'est que mon avis

    Cordialement,
    @+

  5. #5
    Membre actif Avatar de franckcl
    Homme Profil pro
    Developpeur Delphi
    Inscrit en
    septembre 2004
    Messages
    286
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Developpeur Delphi
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : septembre 2004
    Messages : 286
    Points : 213
    Points
    213

    Par défaut

    En fait j'utilise déjà la fonction GetAttributeNS mais pour cela il faut déjà trouver le noeud et c'est là que c'est consommateur de temps.

    Voici ma fonction actuelle qui prend trop de temps:
    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
    Function TMyXML.Read(Path,item, default: String): String;
    Var
      S   : string;
      node: IXMLNode;
      P   : integer;
    Begin
      result := Default;
      delete(path,1,4); // le chemin commence toujours par "xml/"
      p:=1;
      node:=Xml.DocumentElement;
      while (node <> nil) and (P > 0) do
      Begin
        P := Pos('/', Path);
        if (P > 0) then
        Begin
           S := Copy(Path, 1, P - 1);
           delete(Path, 1, P);
           node := node.ChildNodes.FindNode(S); // Si ce n'est pas le dernière identifiant alors c'est un noeud
        End;
      End;
      if assigned(node) and (node.HasAttribute(item)) then result := node.GetAttributeNS(item, '');
    End;
    Je l'appelle de cette manière:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    S := Read('xml/regulator/protocol/','readformat','ERR');
    et S contient donc: "<MSG><CR><LF>"

    Ça marche nickel, mais pour des gros fichiers, cela prend beaucoup de temps, j'ai donc créé ma fonction pour remplir un TStringList et ensuite je fais un indexof pour retrouver un identifiant, ce qui est beaucoup plus rapide (environ 10 fois plus rapide).
    Le problème est ce codage particulier qui est utilisé pour certains caractères.

  6. #6
    Membre confirmé
    Homme Profil pro
    Consultant technique
    Inscrit en
    juillet 2002
    Messages
    505
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

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

    Informations forums :
    Inscription : juillet 2002
    Messages : 505
    Points : 506
    Points
    506

    Par défaut

    Bonsoir,

    Si cela peut aider, j'avais un code en C++ qui faisait quelque chose de similaire. Je l'ai réécris vite fait dans un bloc note, donc il peut y avoir des erreurs de syntaxe ou de formatage.
    Par ailleurs, je ne suis pas certain de la récupération de la valeur finale par : Il faudra surement trouver la bonne manière de récupérer la valeur finale en utilisant GetAttributeNS.

    C'est un code très proche de ce que j'utilise actuellement pour parcourir l'arborescence d'un fichier xml de paramétrage.
    Ici, je l'ai adapté pour ne trouver qu'une seule valeur.

    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
    Function  TMyXML.Read(IXMLNode Level1): String;
    var
      Level2: IXMLNode;
      Level2Count, i : Integer;
    begin
      Result := '';
      if (Level1 <> nil) then
      begin
         Level2Count := Level1.ChildNodes.Count;
         for i := 0 to i < Level2Count do
         begin
             Level2 = Level1.ChildNodes.Get(i);
             if (Level2 <> nil) then
             begin
               if (Level2.GetNodeName() = 'protocol') then
               begin
                 Result := Level2.Text;
                 exit;
               end
               else
               begin
                 Result := Read(Level2);
                 if (Result <> '') then
                   exit;
               end;
             end;
         end;
      end;
    end;
    J'ai beaucoup de paramétrages dans le fichier et pourtant la lecture de ce fichier et d'un autre fichier de lang en XML lors de l'ouverture de l'application est presque instantanée. L'utilisateur ne voit pas de différence de temps de chargement.

    Comme il y a un node, autant utilisant ce système jusqu'au bout plutôt que passer par de la manipulation manuelle de texte au milieu de la fonction pour ensuite utiliser une fonction de recherche de node.
    Ici on boucle sur une fonction de recherche alors que parcourir la boucle ne doit pas prendre beaucoup plus de temps.
    Mais je me trompe peut-être sur ce point.

    J'espère que cela vous aidera.

    Bonne soirée.

  7. #7
    Membre actif Avatar de franckcl
    Homme Profil pro
    Developpeur Delphi
    Inscrit en
    septembre 2004
    Messages
    286
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Developpeur Delphi
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : septembre 2004
    Messages : 286
    Points : 213
    Points
    213

    Par défaut

    Merci gandf,

    J'ai essayé ton code mais la fonction node.text renvoie nil.
    Je pense que c'est parce qu'il n'y a pas de texte dans cette balise.
    Il faudrait qu'on est une truc du genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <protocol> du texte ici </protocol>
    Dans mon cas ce sont des éléments qu'on doit lire.
    Sinon, j'ai vu dans la doc qu'on pouvait récupérer sous forme de chaine tout un noeud avec la propriété "XML"
    dans notre exemple, Level2.XML renvoie :
    [CODE]'<protocol readformat="&lt;MSG&gt;&lt;CR&gt;&lt;LF&gt;"/>'[CODE]
    et le text est toujours codé.

    En attendant, j'ai pu pas mal accélérer le temps de traitement en assignant la propriété Xml.DOMVendor à OMNIXML, j'ai gagné environ 20% en temps.

    Merci

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

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

    Informations forums :
    Inscription : novembre 2002
    Messages : 6 756
    Points : 21 582
    Points
    21 582
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Produits : UPnP, RemoteOffice, FlashPascal

  9. #9
    Membre confirmé
    Homme Profil pro
    Consultant technique
    Inscrit en
    juillet 2002
    Messages
    505
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

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

    Informations forums :
    Inscription : juillet 2002
    Messages : 505
    Points : 506
    Points
    506

    Par défaut

    Aujourd'hui j'ai accès à mon RAD Studio et à sa documentation.

    Au final, pour récupérer la valeur de l'attribut c'est tout simple.
    Si l'attribut porte toujours le même nom, il suffit de faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    node.GetAttribute('readformat')
    Regarde l'aide de delphi : http://docwiki.embarcadero.com/Libra...e.GetAttribute
    Le variant est Null si l'attribut n'est pas trouvé.
    C'est un OleVariant qui est retourné. Peut-être que ceci fonctionnera :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    VarToStr(node.GetAttribute('readformat'))
    Sinon, il est possible de lister tous les attributs et de les parcourir.
    S'il y a un namespace particulier, il y a une autre fonction qu'il faut utiliser mais je ne crois pas que ce soit le cas ici.

    J'utilise la fonction suivante pour préparer le composant de gestion du XML que ce soit pour la lecture ou l'écriture.
    Attention, tout celà est du C++Builder mais tu peux t'en inspirer voir voir les paramètres à initialiser.
    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
     
    const UnicodeString XmlVersion = "1.0";
    const UnicodeString XmlEncoding = "UTF-16";
    const UnicodeString XmlStandAlone = "yes";
     
    void __fastcall TLibraryModule::PrepareXML(TXMLDocument **PXmlDoc, TComponent* PParent, UnicodeString PFile, bool PinitVersion)
    {
    *PXmlDoc = new TXMLDocument(PParent);
    (*PXmlDoc)->DOMVendor =  MSXML_DOM;
    (*PXmlDoc)->NodeIndentStr = "    ";
    (*PXmlDoc)->Options = Xml::Xmlintf::TXMLDocOptions() << doNodeAutoCreate << doNodeAutoIndent << doAttrNull << doAutoPrefix << doNamespaceDecl;
    (*PXmlDoc)->ParseOptions = TParseOptions() << poPreserveWhiteSpace;
    if (PFile != "")
       {
       if (!FileExists(PFile))
          {
          PFile = "";
          }
       }
    (*PXmlDoc)->FileName = PFile;
    (*PXmlDoc)->Active = true;
    if (PinitVersion)
       {
       (*PXmlDoc)->Version = XmlVersion;
       (*PXmlDoc)->Encoding = XmlEncoding;
       (*PXmlDoc)->StandAlone = XmlStandAlone;
       }
    }
    Et ensuite, dans un bloc try j'appel la fonction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    TXMLDocument *XMLDoc = NULL;
    try {
        TLibraryModule::PrepareXML(&XMLDoc, this, Lib->GetProgramDataFolder() + ChangeFileExt(ExtractFileName(Application->ExeName),".xml"), false);
    ...
    Il ne te reste plus qu'à tester et voir si les options peuvent changer les performances en lecture de ton programme.
    Et pour récupérer un message décoder correctement, j'ai l'impression que la fonction est indiquée comme étant obsolète. Il faudrait voir du côté de celle-ci.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TNetEncoding.HTML.Decode

  10. #10
    Membre actif Avatar de franckcl
    Homme Profil pro
    Developpeur Delphi
    Inscrit en
    septembre 2004
    Messages
    286
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Developpeur Delphi
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : septembre 2004
    Messages : 286
    Points : 213
    Points
    213

    Par défaut

    Merci Paul,

    Ca marche avec HtmlDecode, je retrouve bien le bon codage.
    Mais du coup, ma solution n'est pas plus rapide qu'en utilisant les fonctions XML, j'arrive au même résultat.

    Merci Gangf ,

    J'utilisais jusqu'à présent node.GetAttributeNS(item, '') , je viens d'essayer avec node.GetAttribute(item) et cela n'ameliore pas le temps.

    Je vais voir comment je peux éviter de recherche le noeud à chaque requete et utiliser les noeuds calculés précédement afin d'optimiser les temps de traitement.

    Merci à tous les deux.

  11. #11
    Membre chevronné
    Homme Profil pro
    Développeur informatique
    Inscrit en
    novembre 2007
    Messages
    2 365
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : novembre 2007
    Messages : 2 365
    Points : 2 169
    Points
    2 169

    Par défaut

    et avec une regex ???

Discussions similaires

  1. [SAX] Comment récupérer un String entre deux balise xml?
    Par L4BiN dans le forum XML
    Réponses: 6
    Dernier message: 23/06/2006, 09h02
  2. Réponses: 3
    Dernier message: 20/05/2006, 20h42
  3. Réponses: 4
    Dernier message: 11/05/2006, 14h41
  4. comment convertir un fichier xml en tableau de string (java)
    Par l'indien dans le forum XML/XSL et SOAP
    Réponses: 6
    Dernier message: 27/02/2006, 21h00
  5. Réponses: 2
    Dernier message: 31/10/2005, 22h04

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