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

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

  •  28
  • Gishu  · 技术社区  · 15 年前

    考虑下面的XML片段:

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

    如何通过XPath检索“SomeText”值?我用的是Nauman Leghari的(非常好) Visual XPath tool .
    /Obj/Name 返回元素
    /Obj/Name/text() 返回空白

    我不认为这是工具的问题(我可能错了)-我还读到XPath无法提取CDATA(请参阅最后的响应) in this thread

    5 回复  |  直到 15 年前
        1
  •  22
  •   Community Mofi    7 年前

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

    如果使用Xml.Linq,那么XElement.Value将返回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") );
    

    输出:

    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    13 年前

    CDATA部分只是其中的一部分 XPath text node 或者 the XML Infoset 作为“字符信息项的块”。

    显然,您的工具是错误的 . 其他工具,如 the XPath Visualizer 正确突出显示 Name

    /*/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    15 年前

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

    我猜这是工具的问题,源代码可以下载,也许你可以调试它。。。

        4
  •  3
  •   shahkalpesh    15 年前
        5
  •  -3
  •   MANCHUCK    14 年前

    建议使用cdata的md5散列的另一个字段。然后可以使用xpath根据md5进行查询,而不会出现任何问题

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

    然后您可以搜索:

    /sites/site[urlMD5=ed646a3334ca891fd3467db131372140]