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 :

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


Sujet :

Delphi

  1. #1
    Membre averti Avatar de franckcl
    Homme Profil pro
    Developpeur Delphi
    Inscrit en
    Septembre 2004
    Messages
    516
    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 : 516
    Points : 443
    Points
    443
    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 retraité
    Inscrit en
    Janvier 2007
    Messages
    15 021
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 021
    Points : 40 935
    Points
    40 935
    Billets dans le blog
    62
    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
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  3. #3
    Membre averti Avatar de franckcl
    Homme Profil pro
    Developpeur Delphi
    Inscrit en
    Septembre 2004
    Messages
    516
    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 : 516
    Points : 443
    Points
    443
    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 éprouvé
    Avatar de Cirec
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    467
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 467
    Points : 1 072
    Points
    1 072
    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 averti Avatar de franckcl
    Homme Profil pro
    Developpeur Delphi
    Inscrit en
    Septembre 2004
    Messages
    516
    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 : 516
    Points : 443
    Points
    443
    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
    519
    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 : 519
    Points : 523
    Points
    523
    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 averti Avatar de franckcl
    Homme Profil pro
    Developpeur Delphi
    Inscrit en
    Septembre 2004
    Messages
    516
    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 : 516
    Points : 443
    Points
    443
    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
    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
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  9. #9
    Membre confirmé
    Homme Profil pro
    Consultant technique
    Inscrit en
    Juillet 2002
    Messages
    519
    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 : 519
    Points : 523
    Points
    523
    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 averti Avatar de franckcl
    Homme Profil pro
    Developpeur Delphi
    Inscrit en
    Septembre 2004
    Messages
    516
    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 : 516
    Points : 443
    Points
    443
    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 émérite

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 381
    Points : 2 995
    Points
    2 995
    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 Format d'échange (XML, JSON...)
    Réponses: 6
    Dernier message: 23/06/2006, 10h02
  2. Réponses: 3
    Dernier message: 20/05/2006, 21h42
  3. Réponses: 4
    Dernier message: 11/05/2006, 15h41
  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, 22h00
  5. Réponses: 2
    Dernier message: 31/10/2005, 23h04

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