代码之家  ›  专栏  ›  技术社区  ›  Gishu

如何通过XPath检索CDATA标记中的元素文本?

  •  33
  • Gishu  · 技术社区  · 16 年前

    考虑以下xml片段:

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

    如何通过XPath检索“SomeText”值?我正在使用Nauman Leghari的(优秀) Visual XPath tool .
    /Obj/Name 返回元素
    /Obj/Name/text() 返回空白

    我认为这个工具没有问题(我可能错了)-我还读到XPath无法提取CDATA(见最后的回复 in this thread )-听起来有点奇怪。

    6 回复  |  直到 16 年前
        1
  •  22
  •   Community CDub    8 年前

    /Obj/Name/text() 是返回CDATA标记内容的XPath。

    让我失望的是Value属性的行为。对于XMLNode(DOM世界),XMLNode。元素的值属性(使用CDATA或其他方式)返回Null。InnerText属性将为您提供CDATA/Text内容。

    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") );
    

    输出:

    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
    

    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;
    
        2
  •  11
  •   Dimitre Novatchev    14 年前

    CDATA部分只是 XPath 被称为a text node 或在 the XML Infoset 作为“字符信息项块”。

    其他工具,如 the XPath Visualizer Name 计算此XPath表达式时的元素:

    /*/Name/text()
    

    还可以编写一个简单的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>
    

    :

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

    产生正确的结果:

      "SomeText"
    
        3
  •  10
  •   Jason    16 年前

    我认为您引用的线程表明,XPATH忽略了CDATA标记本身,而不是CDATA标记中包含的文本。

        4
  •  3
  •   shahkalpesh    16 年前

    看看这是否有帮助- http://www.zrinity.com/xml/xpath/

        5
  •  -3
  •   MANCHUCK    15 年前

    /Obj/Name/text()