2009-08-06 37 views
10

Tengo un poco de XML de la siguiente manera:Decode CDATA en C#

<section> 
    <description> 
    <![CDATA[ 
     This is a "description" 
     that I have formatted 
    ]]> 
    </description> 
</section> 

estoy acceder a él usando curXmlNode.SelectSingleNode("description").InnerText pero el valor vuelve

\r\n  This is a "description"\r\n  that I have formatted
en lugar de
This is a "description" that I have formatted.

¿Hay una forma sencilla de obtener ese tipo de salida de una sección CDATA? Dejar la etiqueta CDATA real parece tener que regresar de la misma manera.

Respuesta

15

Puede usar Linq para leer CDATA.

XDocument xdoc = XDocument.Load("YourXml.xml"); 
xDoc.DescendantNodes().OfType<XCData>().Count(); 

Es muy fácil obtener el valor de esta manera.

He aquí una buena visión general en MSDN: http://msdn.microsoft.com/en-us/library/bb308960.aspx

para .NET 2.0, es probable que sólo tienen que pasar a través de expresiones regulares:

 string xml = @"<section> 
         <description> 
         <![CDATA[ 
          This is a ""description"" 
          that I have formatted 
         ]]> 
         </description> 
        </section>"; 

     XPathDocument xDoc = new XPathDocument(new StringReader(xml.Trim())); 
     XPathNavigator nav = xDoc.CreateNavigator(); 
     XPathNavigator descriptionNode = 
      nav.SelectSingleNode("/section/description"); 

     string desiredValue = 
      Regex.Replace(descriptionNode.Value 
            .Replace(Environment.NewLine, String.Empty) 
            .Trim(), 
       @"\s+", " "); 

que recorta su valor de nodo, reemplaza los saltos de línea con el vacío, y reemplaza 1+ espacios en blanco con un espacio. No creo que haya otra forma de hacerlo, teniendo en cuenta que CDATA está devolviendo espacios en blanco significativos.

+0

Gracias, pero debería haber sido más específico que estoy haciendo esto en 2.0 en el Marco Compacto. Me gustaría ver si sería más ventajoso pasar a 3.5 en el futuro. – Jess

+0

He editado con otra idea. Sin embargo, no tengo .NET 2.0 CF instalado, así que no estoy 100% seguro de que sea compatible. –

+0

Funciona muy bien. ¡Gracias! – Jess

3

Los bloques CDATA son efectivamente literales. Cualquier espacio en blanco dentro de CDATA es significativo, por definición, de acuerdo con las especificaciones XML. Por lo tanto, obtienes ese espacio en blanco cuando recuperas el valor del nodo. Si desea quitarlo usando sus propias reglas (ya que las especificaciones XML no especifican ninguna forma estándar de eliminar espacios en blanco en CDATA), debe hacerlo usted mismo, usando String.Replace, Regex.Replace, etc., según sea necesario.

9

En realidad, creo que es bastante simple. la sección CDATA se cargará en el XmlDocument como otro XmlNode la diferencia es que este nodo tendrá la propiedad NodeType = CDATA, lo que significa que si tiene el XmlNode node = doc.SelectSingleNode("section/description"); ese nodo tendrá un ChildNode con la propiedad InnerText llena el puro datos, y si desea eliminar los caracteres especiales solo use Trim() y tendrá los datos.

El código se verá así

XmlNode cDataNode = doc.SelectSingleNode("section/description").ChildNodes[0]; 
string finalData = cDataNode.InnerText.Trim(); 

Gracias
XOnDaRocks

8

Creo que la mejor forma de hacerlo es ...

XmlCDataSection cDataNode = (XmlCDataSection)(doc.SelectSingleNode("section/description").ChildNodes[0]); 

string finalData = cDataNode.Data; 
+0

Definitivamente la mejor solución, corta, sin cadena conversiones involucradas y el uso de los métodos existentes System.Xml. – lgrosales

2

Una forma más simple de la solución de Franky:

doc.SelectSingleNode("section/description").FirstChild.Value 

La propiedad Valueis equivalent en la propiedad Data del tipo XmlCDataSection fundido.