PHP: Jak obsłużyć <! [CDATA [z SimpleXMLElement?

97

Zauważyłem, że w przypadku SimpleXMLElementdokumentu zawierającego te znaczniki CDATA zawartość jest zawsze NULL. Jak to naprawić?

Przepraszamy za spamowanie tutaj na temat XML. Od kilku godzin staram się, aby skrypt oparty na XML działał ...

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

Próbowałem pierwszego trafienia w Google, jeśli szukasz „SimpleXMLElement cdata”, ale to nie zadziałało.

Angelo
źródło
W jaki sposób próbujesz uzyskać dostęp do wartości węzła? I czy SimpleXML jest wymagany?
całonocny sklep spożywczy
Wypróbowałem każdą inną funkcję (xml2array i wszystkie), które mogłem znaleźć w Internecie i SimpleXML wydaje się być jedyną, która daje DOBRE wyniki, z wyjątkiem niedziałającego CDATA.
Angelo
1
W pracy wykonujemy dużo analizy XML przy użyciu DOMDocument ( php.net/manual/en/class.domdocument.php ). Działa dobrze w obsłudze CDATA. Daj nam krótki lub napisz trochę więcej kodu, abyśmy mogli zobaczyć, jak pracujesz z SimpleXML.
całonocny sklep spożywczy

Odpowiedzi:

182

Prawdopodobnie nie uzyskujesz do niego dostępu poprawnie. Możesz wyprowadzić go bezpośrednio lub rzutować jako ciąg. (w tym przykładzie rzutowanie jest zbędne, ponieważ echo i tak robi to automatycznie)

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

Możesz mieć więcej szczęścia z LIBXML_NOCDATA:

$content = simplexml_load_string(
    '<content><![CDATA[Hello, world!]]></content>'
    , null
    , LIBXML_NOCDATA
);
Josh Davis
źródło
2
Nie, PHP z jakiegoś powodu całkowicie pomija CDATA. Jakieś inne pomysły?
Angelo
4
Więc to jest błąd. Zaktualizuj PHP / libxml, aż zadziała (nigdy nie miałem żadnych problemów z CDATA i SimpleXML). W przeciwnym razie możesz spróbować szczęścia z LIBXML_NOCDATA.
Josh Davis
5
Wiem, że to stara odpowiedź, ale chciałbym podkreślić, że pierwsza część odpowiedzi jest poprawna . Podczas drukowania wyniku w print_rrzeczywistości nie uzyskujesz do niego dostępu poprawnie. Napisz kod, który faktycznie chcesz - prawdopodobnie z obsadą echolub z (string)obsadą, a przekonasz się, że zawartość jest w porządku. Nie używaj LIBXML_NOCDATA, jest to nieistotne.
IMSoP
7
@IMSoP Dodanie LIBXML_NOCDATA (i nic innego nie zmienia) działa, więc nie jestem pewien, czy jest to nieistotne.
rand
3
@SimonePalazzo XML składa się z różnych "węzłów" - np <anElement>a text node <aChildElement /> <![CDATA a cdata node]]> another text node</anElement>. Węzły CDATA i węzły tekstowe są różnych typów, a SimpleXML śledzi to, dzięki czemu można odzyskać wstawiony kod XML. Kiedy wciskasz obiekt SimpleXML do tablicy, wyrzuca on wiele informacji - węzły CDATA, komentarze, każdy element nie w bieżącej przestrzeni nazw (np. <someNSPrefix:someElement />), pozycja elementu potomnego w tekście itp. LIBXML_NOCDATAkonwertuje węzły CDATA na węzły tekstowe, ale nie naprawia reszty.
IMSoP
48

LIBXML_NOCDATAJest opcjonalny trzeci parametr simplexml_load_file()funkcji. To zwraca obiekt XML ze wszystkimi danymi CDATA przekonwertowanymi na łańcuchy.

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


Napraw CDATA w SimpleXML

Pradip Kharbuja
źródło
LIBXML_NOCDATA jest tym, co sprawiło, że ta działała dla mnie. PHP 5.3.5
Mike_K
1
Twoja odpowiedź to ta, która wyjaśnia znaczenie LIBXML_NOCDATA , dzięki!
Marcio Mazzucato
14

To załatwiło sprawę dla mnie:

echo trim($entry->title);
breez
źródło
Idealne, jeśli chcesz zachować cdata (bez LIBXML_NOCDATA)
maztch
10

To działa idealnie dla mnie.

$content = simplexml_load_string(
    $raw_xml
    , null
    , LIBXML_NOCDATA
);
vijayrana
źródło
0

Kiedy używać LIBXML_NOCDATA?

Dodaję problem przy przekształcaniu XML do JSON.

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

Podczas uzyskiwania dostępu do obiektu SimpleXMLElement pobiera CDATA:

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

Ma sens, LIBXML_NOCDATAponieważ json_encodenie mam dostępu do SimpleXMLElement, aby wywołać funkcję rzucania ciągów, zgaduję, że jest to __toString()odpowiednik.

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