2009-02-20 34 views
27

Considere el siguiente fragmento xml:¿Cómo recupero el texto del elemento dentro de la marca CDATA a través de XPath?

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

¿Cómo recupero el valor "SomeText" a través de XPath? Estoy usando Nauman Leghari (excelente) Visual XPath tool.
/Obj/Name devuelve el elemento
/Obj/Name/text() vuelve blanco

no creo que es un problema con la herramienta (puedo estar equivocado) - Yo también leen XPath no puede extraer CDATA (Ver última respuesta in this thread) - que suena un poco extraño para mí.

Respuesta

8

Creo que el hilo al que se hace referencia dice que el marcado CDATA es ignorado por XPATH, no el texto contenido en el marcado CDATA.

mi conjetura es que su un problema con la herramienta, el código fuente está disponible para su descarga, tal vez se puede depurarlo ...

+1

Básicamente tenían una caja de conmutación DisplayNode gigante() en el tipo de escaneado XMLNode .. .con el bloque de casos específico con un TODO Inside it :) Problema con la herramienta que es. – Gishu

9

secciones CDATA son sólo una parte de lo que en XPath se conoce como un text node o en the XML Infoset como "trozos de elementos de información de carácter".

Obviamente, su herramienta está mal. Otras herramientas, como the XPath Visualizer resaltan correctamente el texto del elemento Name la hora de evaluar esta expresión XPath:

/*/Name/text() 

También se puede escribir una simple transformación 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> 

Cuando se aplica esta transformación en el documento XML proporcionado:

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

el resultado correcto se produce:

"SomeText" 
19

/Obj/Name/text() es el XPath para devolver el contenido del marcado CDATA.

Lo que me sorprendió fue el comportamiento de la propiedad Value. Para un XMLNode (mundo DOM), la propiedad XmlNode.Value de un elemento (con CDATA u otro) devuelve nulo. La propiedad InnerText le daría el contenido CDATA/Text. Si usa Xml.Linq, XElement.Value devuelve el contenido de 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")); 

Salida:

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 

Resultó que el autor de Visual XPath tenido un TODO para el tipo CDATA de XMLNodes. Un pequeño fragmento de código y ahora tengo soporte para 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; 
+1

> el comportamiento de la propiedad Value Está viendo el efecto de diferentes modelos de datos reflejados por diferentes API. Muchas API siguen el XML Infoset que distingue el contenido de texto y CData. Pero XPath no. . XPathDocument API de .NET sigue el modelo XPath para que no pueda ver explícitamente CDATA, – Richard

-3

Una sugerencia sería tener otro campo del hash md5 de la cdata. A continuación, puede utilizar XPath para consultar el apagado basado MD5 sin problema

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

Ahora tiene que buscar:

/sites/site[urlMD5=ed646a3334ca891fd3467db131372140] 
+0

Si la notación xpath permite buscar directamente el nodo relacionado, no hay necesidad de esto :-) –

Cuestiones relacionadas