Как сохранить DOMDocument от сохранения <as & lt - PullRequest
8 голосов
/ 06 августа 2010

Я использую simpleXML для добавления дочернего узла в один из моих документов XML ... когда я выполняю print_r для моего объекта simpleXML, < все еще отображается как < в источнике представления,Однако после того, как я сохраню этот объект обратно в XML с помощью DOMDocument, < преобразуется в &lt;, а > преобразуется в &gt;

Есть идеи о том, как изменить это поведение?Я попытался добавить dom->substituteEntities = false;, но это не помогло.

    //Convert SimpleXML element to DOM and save
    $dom = new DOMDocument('1.0');
    $dom->preserveWhiteSpace = false;
    $dom->formatOutput = false;
    $dom->substituteEntities = false;
    $dom->loadXML($xml->asXML());
    $dom->save($filename);

Здесь я использую <: </p>

$new_hint = '<![CDATA[' . $value[0] . ']]>';               
$PrintQuestion->content->multichoice->feedback->hint->Passage->Paragraph->addChild('TextFragment', $new_hint);

Проблема в том, что яиспользуя простой XML для итерации по определенным узлам в документе XML, и если атрибут соответствует заданному идентификатору, конкретный дочерний узел добавляется с помощью CDATA.Затем, после всей обработки, я сохраняю XML обратно в файл, используя DOMDocument, где <преобразуется в <и т. Д. </p>

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

http://pastie.org/1079562

Ответы [ 2 ]

10 голосов
/ 06 августа 2010

SimpleXML и php5 Модуль DOM использует одинаковое внутреннее представление документа (облегчается libxml ).Вы можете переключаться между обоими API без необходимости повторного анализа документа с помощью simplexml_import_dom () и dom_import_simplexml () .
Т.е. если вы действительно хотите / должны выполнить итерацию с API SimpleXML, как только вы 'найдя свой элемент, вы можете переключиться на API DOM и создать раздел CData в том же документе.

<?php
$doc = new SimpleXMLElement('<a>
  <b id="id1">a</b>
  <b id="id2">b</b>
  <b id="id3">c</b>
</a>');


foreach( $doc->xpath('b[@id="id2"]') as $b ) {
  $b = dom_import_simplexml($b);
  $cdata = $b->ownerDocument->createCDataSection('0<>1');
  $b->appendChild($cdata);
  unset($b);
}

echo $doc->asxml();

печать

<?xml version="1.0"?>
<a>
  <b id="id1">a</b>
  <b id="id2">b<![CDATA[0<>1]]></b>
  <b id="id3">c</b>
</a>
3 голосов
/ 06 августа 2010

Проблема в том, что вы, скорее всего, добавляете это как строку, а не как элемент.

Итак, вместо:

$simple->addChild('foo', '<something/>');

, который будет рассматриваться как текст:

$child = $simple->addChild('foo');
$child->addChild('something');

Вы не можете иметь литерал < в теле документа XML, если это не открытие тега.

Редактировать: После того, что вы описываете в комментариях, я думаю, что вы после:

DomDocument::createCDatatSection()

$child = $dom->createCDataSection('your < cdata > body ');
$dom->appendChild($child);

Edit2: После прочтения вашего редактирования я могу сказать только одно:

You're doing it wrong... Нельзя добавить элементы в качестве строкового значения для другого элемента. Извините, вы просто не можете. Вот почему это ускользает от вещей, потому что DOM и SimpleXML созданы для того, чтобы вы всегда создавали корректный XML. Вам нужно создать элемент как объект ... Итак, если вы хотите создать дочерний элемент CDATA, вам нужно сделать что-то вроде этого:

$child = $PrintQuestion.....->addChild('TextFragment');
$domNode = dom_import_simplexml($child);
$cdata = $domNode->ownerDocument->createCDataSection($value[0]); 
$domNode->appendChild($cdata);

Вот и все, что нужно ...

...