PHP: как работать с <! [CDATA [с SimpleXMLElement?

97

Я заметил, что при использовании SimpleXMLElementв документе, который содержит эти теги CDATA, содержимое всегда NULL. Как это исправить?

Также извините за спам об XML. Я уже несколько часов пытаюсь заставить работать скрипт на основе XML ...

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

Я попробовал сделать первое попадание в Google, если вы искали "SimpleXMLElement cdata", но это не сработало.

Анджело
источник
Как вы пытаетесь получить доступ к значению узла? И является ли SimpleXML требованием?
allnightgrocery
Я пробовал все другие функции (xml2array и все остальное), которые я мог найти в Интернете, и SimpleXML, похоже, единственный, который дает ХОРОШИЕ результаты, за исключением того, что CDATA не работает.
Анджело
1
Мы часто выполняем синтаксический анализ XML на работе, используя DOMDocument ( php.net/manual/en/class.domdocument.php ). Он отлично работает с CDATA. Кратко или опубликуйте еще немного кода, чтобы мы увидели, как вы работаете с SimpleXML.
allnightgrocery

Ответы:

182

Вероятно, вы неправильно обращаетесь к нему. Вы можете вывести его напрямую или преобразовать в строку. (в этом примере литье лишнее, так как echo все равно делает это автоматически)

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

Возможно, вам повезет больше с LIBXML_NOCDATA:

$content = simplexml_load_string(
    '<content><![CDATA[Hello, world!]]></content>'
    , null
    , LIBXML_NOCDATA
);
Джош Дэвис
источник
2
Нет, PHP по какой-то причине полностью пропускает CDATA. Есть другие идеи?
Анджело
4
Тогда это ошибка. Обновите PHP / libxml, пока он не заработает (у меня никогда не было проблем с CDATA и SimpleXML.) В противном случае вы можете попытать счастья с LIBXML_NOCDATA.
Джош Дэвис,
5
Я знаю, что это старый ответ, но я хотел бы подчеркнуть, что первая часть этого ответа верна . Когда вы распечатываете результат с помощью, print_rвы действительно не получаете к нему доступа правильно. Напишите код, который вам действительно нужен - возможно, с приведением echoили с (string)приведением, и вы обнаружите, что с содержимым все в порядке. Не используйте LIBXML_NOCDATA, это не имеет значения.
IMSoP
7
@IMSoP Добавление LIBXML_NOCDATA (и ничего не меняющее) работает, поэтому я не уверен, что это неактуально.
Rand
3
@SimonePalazzo XML состоит из различных «узлов», например <anElement>a text node <aChildElement /> <![CDATA a cdata node]]> another text node</anElement>. CDATA и текстовые узлы бывают разных типов, и SimpleXML отслеживает это, чтобы вы могли вернуть введенный XML. Когда вы сжимаете объект SimpleXML в массив, он отбрасывает много информации - узлы CDATA, комментарии, любой элемент, не в текущем пространстве имен (например <someNSPrefix:someElement />) позиция дочернего элемента в тексте и т. д. LIBXML_NOCDATAпреобразует узлы CDATA в текстовые узлы, но не исправляет остальные.
IMSoP
48

LIBXML_NOCDATAЯвляется необязательным третьим параметром simplexml_load_file()функции. Это возвращает объект XML со всеми данными CDATA, преобразованными в строки.

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


Исправить CDATA в SimpleXML

Прадип Харбуджа
источник
LIBXML_NOCDATA - вот что заставило меня работать. PHP 5.3.5
Mike_K
1
Ваш ответ объясняет значение LIBXML_NOCDATA , спасибо!
Marcio Mazzucato
14

Это помогло мне:

echo trim($entry->title);
ветерок
источник
Идеально, если вам нужно сохранить cdata (без LIBXML_NOCDATA)
maztch
Можете показать это как ответ на вопрос?
Питер Хёйлунд Андерсен,
10

Это работает идеально для меня.

$content = simplexml_load_string(
    $raw_xml
    , null
    , LIBXML_NOCDATA
);
Виджайрана
источник
0

Когда использовать LIBXML_NOCDATA?

Добавляю проблему при преобразовании XML в JSON.

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

При доступе к объекту SimpleXMLElement он получает CDATA:

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

У меня есть смысл использовать, LIBXML_NOCDATAпотому что у json_encodeменя нет доступа к SimpleXMLElement для запуска функции приведения строк, я предполагаю __toString()эквивалент.

$xml = simplexml_load_string("<foo><content><![CDATA[Hello, world!]]></content></foo>", null, LIBXML_NOCDATA);
echo json_encode($xml);
/*
 {
   "content": "Hello, world!"
 }
*/
Габриэль Гленн
источник