Comment récupérer le texte de L'élément dans le balisage CDATA via XPath?

Considérons le fragment xml suivant:

<Obj>
   <Name><![CDATA[SomeText]]></Name>
</Obj>

Comment récupérer la valeur" SomeText " via XPath? J'utilise L'outil Visual XPath de Nauman Leghari (excellent) .
/Obj/Name retourne l'élément
/Obj/Name/text() retourne vide

Je ne pense pas que ce soit un problème avec l'outil (je peux me tromper) - j'ai aussi lu que XPath ne peut pas extraire CDATA (voir la dernière réponse dans ce fil) - ce qui me semble un peu bizarre.

28
demandé sur Gishu 2009-02-20 07:51:25

5 réponses

Je pense que le thread que vous avez référencé dit que le balisage CDATA lui-même est ignoré par XPATH, pas le texte contenu dans le balisage CDATA.

Je suppose que c'est un problème avec l'outil, le code source est disponible en téléchargement, peut-être que vous pouvez le déboguer...

8
répondu Jason 2009-02-20 05:25:29

/Obj/Name/text() est le XPath pour renvoyer le contenu du balisage CDATA.

Ce qui m'a jeté était le comportement de la propriété Value. Pour un XmlNode (monde DOM), le XmlNode.La propriété Value d'un élément (avec CDATA ou autre) renvoie Null. La propriété InnerText vous donnera le contenu CDATA / Text. Si vous utilisez Xml.Linq, XElement.Value renvoie le contenu CDATA.

string sXml = @"
<object>
    <name><![CDATA[SomeText]]></name>
    <name>OtherName</name>
</object>";

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml( sXml );
XmlNamespaceManager nsMgr = new XmlNamespaceManager(xmlDoc.NameTable);

Console.WriteLine(@"XPath = /object/name" );
WriteNodesToConsole(xmlDoc.SelectNodes("/object/name", nsMgr));

Console.WriteLine(@"XPath = /object/name/text()" );
WriteNodesToConsole( xmlDoc.SelectNodes("/object/name/text()", nsMgr) );

Console.WriteLine(@"Xml.Linq = obRoot.Elements(""name"")");
XElement obRoot = XElement.Parse( sXml );
WriteNodesToConsole( obRoot.Elements("name") );

Sortie:

XPath = /object/name
        NodeType = Element
        Value = <null>
        OuterXml = <name><![CDATA[SomeText]]></name>
        InnerXml = <![CDATA[SomeText]]>
        InnerText = SomeText

        NodeType = Element
        Value = <null>
        OuterXml = <name>OtherName</name>
        InnerXml = OtherName
        InnerText = OtherName

XPath = /object/name/text()
        NodeType = CDATA
        Value = SomeText
        OuterXml = <![CDATA[SomeText]]>
        InnerXml =
        InnerText = SomeText

        NodeType = Text
        Value = OtherName
        OuterXml = OtherName
        InnerXml =
        InnerText = OtherName

Xml.Linq = obRoot.Elements("name")
        Value = SomeText
        Value = OtherName

S'est avéré que L'auteur de Visual XPath avait un TODO pour le type CDATA de XmlNodes. Un petit extrait de code et J'ai le support CDATA maintenant. le texte d'alt

MainForm.cs

private void Xml2Tree( TreeNode tNode, XmlNode xNode)
{
   ...
   case XmlNodeType.CDATA:
      //MessageBox.Show("TODO: XmlNodeType.CDATA");
      // Gishu                    
      TreeNode cdataNode = new TreeNode("![CDATA[" + xNode.Value + "]]");
      cdataNode.ForeColor = Color.Blue;
      cdataNode.NodeFont = new Font("Tahoma", 12);
      tNode.Nodes.Add(cdataNode);
      //Gishu
      break;
19
répondu Gishu 2017-02-08 14:10:26

Les sections CDATA ne sont qu'une partie de ce que XPath est connu comme un text node ou dans L'Infoset XML comme "morceaux d'éléments d'information de caractère".

Évidemment, votre outil est faux. Autres outils, comme le visualiseur XPath mettez correctement en surbrillance le texte de l'élément Name lors de l'évaluation de cette expression XPath:

/*/Name/text()

On peut aussi écrire une simple transformation XSLT:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>
<xsl:template match="/">
  "<xsl:value-of select="/*/Name"/>"
</xsl:template>
</xsl:stylesheet>

Quand cela la transformation est appliquée sur le document XML fourni :

<Obj>
    <Name><![CDATA[SomeText]]></Name>
</Obj>

Le résultat correct est produite:

  "SomeText"
9
répondu Dimitre Novatchev 2011-04-08 01:57:19

Voir si cela aide - http://www.zrinity.com/xml/xpath/
XPATH = /Obj/Nom/text()

3
répondu shahkalpesh 2009-02-20 05:37:07

Une suggestion serait d'avoir un autre champ du hachage md5 du cdata. Vous pouvez ensuite utiliser xpath pour interroger le md5 sans problème

<sites>
  <site>
    <name>Google</name>
    <url><![CDATA[http://www.google.com]]></url>
    <urlMD5>ed646a3334ca891fd3467db131372140</urlMD5>
  </site>
</sites>

Ensuite, vous pouvez rechercher:

/sites/site[urlMD5=ed646a3334ca891fd3467db131372140]
-3
répondu MANCHUCK 2010-05-26 16:15:26