PHP: ¿Cómo manejar <! [CDATA [con SimpleXMLElement?

97

Noté que cuando se usa SimpleXMLElementen un documento que contiene esas etiquetas CDATA, el contenido es siempre NULL. ¿Cómo puedo solucionar esto?

Además, lo siento por enviar spam sobre XML aquí. He estado tratando de hacer funcionar un script basado en XML durante varias horas ...

<content><![CDATA[Hello, world!]]></content>

Probé el primer resultado en Google si buscas "SimpleXMLElement cdata", pero no funcionó.

Angelo
fuente
¿Cómo intentas acceder al valor del nodo? Y, ¿SimpleXML es un requisito?
Supermercado nocturno el
Probé todas las demás funciones (xml2array y todas) que pude encontrar en la web y SimpleXML parece ser la única que da BUENOS resultados, excepto que CDATA no funciona.
Angelo
1
Hacemos mucho análisis de XML en el trabajo usando DOMDocument ( php.net/manual/en/class.domdocument.php ). Funciona bien en el manejo de CDATA. Dale un breve código o publica un poco más para que veamos cómo estás trabajando con SimpleXML.
Supermercado nocturno

Respuestas:

182

Probablemente no esté accediendo correctamente. Puede generarlo directamente o convertirlo en una cadena. (en este ejemplo, el casting es superfluo, ya que el eco lo hace automáticamente de todos modos)

$content = simplexml_load_string(
    '<content><![CDATA[Hello, world!]]></content>'
);
echo (string) $content;

// or with parent element:

$foo = simplexml_load_string(
    '<foo><content><![CDATA[Hello, world!]]></content></foo>'
);
echo (string) $foo->content;

Quizás tengas mejor suerte con LIBXML_NOCDATA:

$content = simplexml_load_string(
    '<content><![CDATA[Hello, world!]]></content>'
    , null
    , LIBXML_NOCDATA
);
Josh Davis
fuente
2
No, PHP omite CDATA por completo por alguna razón. ¿Alguna otra idea?
Angelo
4
Entonces es un error. Actualice PHP / libxml hasta que funcione (nunca he tenido ningún problema con CDATA y SimpleXML). De lo contrario, puede probar suerte con LIBXML_NOCDATA.
Josh Davis
5
Sé que esta es una respuesta antigua, pero me gustaría enfatizar que la primera parte de esta respuesta es correcta . Cuando imprime el resultado con print_r, de hecho no está accediendo a él correctamente. Escriba el código que realmente desea, probablemente con echoo con un (string)elenco, y encontrará que el contenido está bien. No utilice LIBXML_NOCDATA, es irrelevante.
IMSoP
7
@IMSoP Agregar LIBXML_NOCDATA (y no cambiar nada más) funciona, así que no estoy tan seguro de que sea irrelevante.
rand
3
@SimonePalazzo XML consta de varios "nodos" diferentes, por ejemplo <anElement>a text node <aChildElement /> <![CDATA a cdata node]]> another text node</anElement>. Los nodos CDATA y de texto son de diferentes tipos, y SimpleXML rastrea esto para que pueda recuperar el XML que ingresó. Cuando aprieta un objeto SimpleXML en una matriz, arroja mucha información: nodos CDATA, comentarios, cualquier elemento que no sea en el espacio de nombres actual (p <someNSPrefix:someElement />. ej. ), la posición del elemento hijo en el texto, etc. LIBXML_NOCDATAconvierte los nodos CDATA en nodos de texto, pero no corrige el resto.
IMSoP
48

El LIBXML_NOCDATAtercer parámetro de simplexml_load_file()función es opcional . Esto devuelve el objeto XML con todos los datos CDATA convertidos en cadenas.

$xml = simplexml_load_file($this->filename, 'SimpleXMLElement', LIBXML_NOCDATA);
echo "<pre>";
print_r($xml);
echo "</pre>";


Arreglar CDATA en SimpleXML

Pradip Kharbuja
fuente
LIBXML_NOCDATA es lo que hizo que esto funcionara para mí. PHP 5.3.5
Mike_K
1
Su respuesta es la que explica el significado de LIBXML_NOCDATA , ¡gracias!
Marcio Mazzucato
14

Esto funcionó para mí:

echo trim($entry->title);
Breez
fuente
Perfecto si necesita mantener el cdata (sin LIBXML_NOCDATA)
maztch
10

Esto está funcionando perfecto para mí.

$content = simplexml_load_string(
    $raw_xml
    , null
    , LIBXML_NOCDATA
);
vijayrana
fuente
0

¿Cuándo usarlo LIBXML_NOCDATA?

Agrego el problema al transformar XML a JSON.

$xml = simplexml_load_string("<foo><content><![CDATA[Hello, world!]]></content></foo>");
echo json_encode($xml, true); 
/* prints
   {
     "content": {}
   }
 */

Al acceder al objeto SimpleXMLElement, obtiene el CDATA:

$xml = simplexml_load_string("<foo><content><![CDATA[Hello, world!]]></content></foo>");
echo $xml->content; 
/* prints
   Hello, world!
*/

Tiene sentido usarlo LIBXML_NOCDATAporque json_encodeno accedo al SimpleXMLElement para activar la función de conversión de cadenas, supongo que es __toString()equivalente.

$xml = simplexml_load_string("<foo><content><![CDATA[Hello, world!]]></content></foo>", null, LIBXML_NOCDATA);
echo json_encode($xml);
/*
 {
   "content": "Hello, world!"
 }
*/
Gabriel Glenn
fuente