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.

Angelo
fonte
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
);
Josh Davis
fonte
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

Pradip Kharbuja
fonte
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);
Breez
fonte
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
);
vijayrana
fonte
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!"
 }
*/
Gabriel glenn
fonte