2009-02-20 8 views
27

は、次のXMLフラグメントを考えてみましょう:XPathを使用してCDATAマークアップ内の要素テキストを取得するにはどうすればよいですか?

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

私は、XPathを経由して "SomeText" の値を取得するにはどうすればよいですか?私はNauman Leghari(優秀)Visual XPath toolを使用しています。
/Obj/Name空白

要素に
/Obj/Name/text()リターンを返す私は(私が間違っている可能性があります)その]ツールに問題があることを考えていない - 私はまた、XPathはCDATAを抽出することはできません読んで(最後の応答in this threadを参照してください) - どの私にはちょっと奇妙な音。

答えて

8

あなたが参照したスレッドは、CDATAマークアップ自体がCDATAマークアップに含まれているテキストではなくXPATHによって無視されると言っていると思います。

私の推測では...ツールとの問題、ソースコードがダウンロード可能である、多分あなたはそれをデバッグできることを

+1

をそれは基本的にスキャンされたXMLNodeの種類の巨大DisplayNode()スイッチケースを持っていました。.. 。特定のケースブロックでTODOを使用しています。その中にツールがあります。 – Gishu

9

CDATAセクションはXPathで「文字情報項目の塊」としてtext nodeとして、またはthe XML Infosetで知られていることのほんの一部です。

あなたのツールは間違っているです。この変換が適用されると

<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> 

:一つは、単純なXSLT変換を書くことができます

/*/Name/text() 

:このXPath式を評価するときthe XPath Visualizerが正しくName要素のテキストをハイライトとして、他のツール、提供されたXMLドキュメントの

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

正しい結果が生成される:

"SomeText" 
19

/Obj/Name/text()はCDATAマークアップのコンテンツを返すためのXPathです。

私を捨てたのは、Valueプロパティの動作でした。 XMLNode(DOMワールド)の場合、Element(CDATAまたはそれ以外の場合)のXmlNode.ValueプロパティはNullを返します。 InnerTextプロパティはCDATA/Textコンテンツを提供します。 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 

XMLNodeののCDATAタイプのためのTODOを持っていたビジュアルのXPathの作者が判明。少しコードスニペットと私は今CDATAサポートを持っています。 alt text

メインフォーム。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; 
+1

> Valueプロパティの動作 異なるAPIによって異なるデータモデルが反映されています。多くのAPIは、テキストとCDataコンテンツを区別するXML Infosetに従います。しかし、XPathはそうではありません。 .NETのXPathDocument APIがXPathモデルに従っているため、明示的にCDATAを見ることができません。 – Richard

-3

cdataのmd5ハッシュの別のフィールドを持つことをお勧めします。そして、あなたが検索することができますが、その後、無問題

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

でMD5をオフに基づいて、クエリにXPathを使用することができます。

/sites/site[urlMD5=ed646a3334ca891fd3467db131372140] 
+0

xpath表記が関連ノードを直接検索できる場合は、これは必要ありません:-) –

関連する問題