PHP: Como lidar com <! [CDATA [com SimpleXMLElement?


97

Percebi que, ao usar SimpleXMLElementem um documento que contém essas tags CDATA, o conteúdo é sempre NULL. Como faço para corrigir isso?

Além disso, desculpe por enviar spam sobre XML aqui. Estou tentando fazer um script baseado em XML funcionar há várias horas ...

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

Tentei o primeiro hit no Google se você pesquisar "SimpleXMLElement cdata", mas não funcionou.


Como você está tentando acessar o valor do nó? E o SimpleXML é um requisito?
— mercearia noturna

Tentei todas as outras funções (xml2array e tudo) que pude encontrar na web e SimpleXML parece ser a única que dá BONS resultados, exceto para o CDATA não funcionar.
— Angelo

1
Fazemos muitas análises de XML no trabalho usando DOMDocument ( php.net/manual/en/class.domdocument.php ). Ele funciona muito bem no manuseio de CDATA. Faça um breve resumo ou poste um pouco mais de código para vermos como você está trabalhando com SimpleXML.
— mercearia noturna

Respostas:


182

Provavelmente, você não está acessando corretamente. Você pode enviá-lo diretamente ou convertê-lo como uma string. (neste exemplo, a projeção é supérflua, já que o eco faz automaticamente de qualquer maneira)

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

Você pode ter mais sorte com LIBXML_NOCDATA:

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

2
Não, o PHP pula o CDATA completamente por algum motivo. Alguma outra ideia?
— Angelo

4
Então é um bug. Atualize o PHP / libxml até que funcione (nunca tive problemas com CDATA e SimpleXML). Caso contrário, você pode tentar a sorte com LIBXML_NOCDATA.
— Josh Davis

5
Sei que é uma resposta antiga, mas gostaria de enfatizar que a primeira parte da resposta está correta . Quando você imprime o resultado com print_rvocê realmente não está acessando corretamente. Escreva o código que você realmente deseja - provavelmente com echo, ou com (string)elenco, e você descobrirá que o conteúdo é adequado. Não use LIBXML_NOCDATA, é irrelevante.
— IMSoP

7
@IMSoP Adicionar LIBXML_NOCDATA (e não mudar mais nada) funciona, então não tenho certeza se é irrelevante.
— rand

3
@SimonePalazzo XML consiste em vários "nós" diferentes - por exemplo <anElement>a text node <aChildElement /> <![CDATA a cdata node]]> another text node</anElement>. O CDATA e os nós de texto são tipos diferentes, e SimpleXML rastreia isso para que você possa recuperar o XML inserido. Quando você espreme um objeto SimpleXML em uma matriz, ele joga fora muitas informações - nós CDATA, comentários, qualquer elemento não no namespace atual (por exemplo <someNSPrefix:someElement />), a posição do elemento filho no texto, etc. LIBXML_NOCDATAconverte nós CDATA em nós de texto, mas não corrige o resto.
— IMSoP

48

O LIBXML_NOCDATAé o terceiro parâmetro opcional de simplexml_load_file()função. Isso retorna o objeto XML com todos os dados CDATA convertidos em strings.

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


Corrigir CDATA em SimpleXML


LIBXML_NOCDATA é o que fez isso funcionar para mim. PHP 5.3.5
— Mike_K

1
Sua resposta é aquela que explica o significado de LIBXML_NOCDATA , obrigado!
— Marcio Mazzucato

14

Isso funcionou para mim:

echo trim($entry->title);

Perfeito se você precisa manter o cdata (sem LIBXML_NOCDATA)
— maztch

10

Isso está funcionando perfeitamente para mim.

$content = simplexml_load_string(
    $raw_xml
    , null
    , LIBXML_NOCDATA
);

0

Quando usar LIBXML_NOCDATA?

Acrescento o problema ao transformar XML em JSON.

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

Ao acessar o objeto SimpleXMLElement, obtém o CDATA:

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

Faz sentido usar LIBXML_NOCDATAporque json_encodenão acesse o SimpleXMLElement para acionar o recurso de fundição de string, estou supondo um __toString()equivalente.

$xml = simplexml_load_string("<foo><content><![CDATA[Hello, world!]]></content></foo>", null, LIBXML_NOCDATA);
echo json_encode($xml);
/*
 {
   "content": "Hello, world!"
 }
*/
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.