web-dev-qa-db-fra.com

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

Considérez le fragment xml suivant:

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

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

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

30
Gishu

je pense que le fil 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 pour téléchargement, peut-être que vous pouvez le déboguer ...

9
Jason

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

Ce qui m'a bouleversé, c'est le comportement de la propriété Value. Pour un XMLNode (monde DOM), la propriété XmlNode.Value d'un élément (avec CDATA ou autre) renvoie Null. La propriété InnerText vous donnerait le contenu CDATA/texte. 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") );

Production:

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

Il 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 maintenant le support CDATA. alt text

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;
22
Gishu

Les sections CDATA ne sont qu'une partie de ce que dans XPath est connu sous le nom de text node ou dans l'ensemble d'informations XML sous la forme de "blocs d'informations de caractère"

Évidemment, votre outil est erroné . D'autres outils, comme le visualiseur XPath mettent correctement en surbrillance le texte de l'élément Name lors de l'évaluation de cette expression XPath :

/*/Name/text()

On peut également é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>

Lorsque cette transformation est appliquée sur le document XML fourni :

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

le résultat correct est produit:

  "SomeText"
10
Dimitre Novatchev

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

3
shahkalpesh