Создать или вставить XML в CDATA

Я что-то тестировал, но не могу заставить его работать, вот проблема:

У меня есть xml:

<?xml version="1.0" encoding="UTF-8"?>
<history>
    <name>
        <age/>
    </name>
</history>

Я хотел бы вставить CDATA в этот XML, и содержимое CDATA также является частью XML, что-то вроде этого:

<?xml version="1.0" encoding="UTF-8"?>
<history>
    <![CDATA[
    <name>
        <age/>
    </name>
    ]]>
</history>

Я использую DOMDocument для создания XML:

        header('Content-Type: text/xml');
        $xml = new DOMDocument("1.0","UTF-8");
        $base = $xml->appendChild($xml->createElement('history'));

        $name = $base->appendChild($xml->createElement('name'));
        $age = $name->appendChild($xml->createElement('age'));
        $test = $xml->saveXML();

        $xml->getElementsByTagName('history')->item(0)->appendChild($xml->createCDATASection($test));

        $xml->formatOutput = true;
        echo $xml->saveXML();

он генерирует этот XML:

<?xml version="1.0" encoding="UTF-8"?>
<history>
    <name>
    <age/>
    </name>
    <![CDATA[<?xml version="1.0" encoding="UTF-8"?><history><name><age/></name></history>]]>
</history>

Проблемы, с которыми я сталкиваюсь в данный момент:

  1. То, как я смотрю на работу CDATA, похоже, что мне нужно заполнить весь "внутренний xml", прежде чем я смогу вырезать этот "внутренний xml", а затем создать раздел cdata и вставить его в раздел cdata
  2. Я использую временное решение, которое является str_replace, но я хотел бы максимально использовать функцию domdocument createCData.

1 ответ

Вы на правильном пути. Разделы CDATA - это текст для внешнего документа, фрагмент xml внутри CDATA - это собственный документ или фрагмент.

$xml = new DOMDocument("1.0","UTF-8");
$xml->appendChild($historyNode = $xml->createElement('history'));

$innerXml = new DOMDocument("1.0","UTF-8");
$innerXml->appendChild($nameNode = $innerXml->createElement('name'));
$nameNode->appendChild($ageNode = $innerXml->createElement('age'));

$fragment = $innerXml->saveXml($innerXml->documentElement);

$historyNode->appendChild($xml->createCDATASection($fragment));

$xml->formatOutput = true;
echo $xml->saveXML();

Выход:

<?xml version="1.0" encoding="UTF-8"?>
<history><![CDATA[<name><age/></name>]]></history>

Это будет работать только в том случае, если фрагмент имеет единственный корневой узел (это действительный документ XML). Если на верхнем уровне есть несколько узлов, вам понадобится фиктивный узел. Я добавил адрес в следующий пример, чтобы показать разницу:

$xml = new DOMDocument("1.0","UTF-8");
$xml->appendChild($historyNode = $xml->createElement('history'));

$innerXml = new DOMDocument("1.0","UTF-8");
$innerXml->appendChild($fragmentNode = $innerXml->createElement('fragment'));
$fragmentNode->appendChild($nameNode = $innerXml->createElement('name'));
$nameNode->appendChild($ageNode = $innerXml->createElement('age'));
$fragmentNode->appendChild($addressNode = $innerXml->createElement('address'));

$fragment = '';
foreach ($fragmentNode->childNodes as $childNode) {
  $fragment .= $innerXml->saveXml($childNode);
}

$historyNode->appendChild($xml->createCDATASection($fragment));

$xml->formatOutput = true;
echo $xml->saveXML();

Выход:

<history><![CDATA[<name><age/></name><address/>]]></history>
Другие вопросы по тегам