Меньше и больше чем знак в DOMDocument XML .lsg - PullRequest
0 голосов
/ 01 июля 2019

Я пытаюсь добавить некоторые новые элементы в файл lsg (состоящий из XML) с помощью сценария PHP. Затем файл lsg импортируется в limesurvey. Проблема в том, что я не могу правильно добавить символы, такие как <и>, которые мне нужно добавить. Они отображаются только как ссылки на сущности (например, <и>), которые не работают должным образом при импорте в limesurvey. Если я вручную изменю ссылки на сущности на <и>

Я пытался использовать PHP DOMDocument для этого. Мой код выглядит примерно так:

$dom = new DOMDocument();
$dom->load('template.lsg');

$subquestions = $dom->getElementById('subquestions');

$newRow = $dom->createElement('row');
$subquestions->appendChild($newRow);

$properties[] = array('name' => 'qid', 'value' => "![CDATA[1]]");

foreach ($properties as $prop) {
    $element = $dom->createElement($prop['name']);
    $text = $dom->createTextNode($prop['value']);
    $startTag = $dom->createEntityReference('lt');
    $endTag = $dom->createEntityReference('gt');
    $element->appendChild($startTag);
    $element->appendChild($text);
    $element->appendChild($endTag);
    $supplier->appendChild($element);
}

$response = $dom->saveXML();
$dom->save('test.lsg');

Результат этой строки такой:

<row>
        <qid>&lt;![CDATA[7]]&lt;</qid>
</row>

Пока должно выглядеть так:

<row>
    <qid><![CDATA[7]]></qid>
</row>

Есть предложения?

1 Ответ

1 голос
/ 01 июля 2019

CDATA-секции - это особый вид текстовых узлов.Они кодируют / декодируют намного меньше, и они сохраняют начальные / конечные пробелы.Таким образом, анализатор DOM должен читать те же значения из следующих двух примеров узлов:

<examples>
  <example>text<example>
  <example><![CDATA[text]]]></example>
</examples>

Чтобы создать раздел CDATA, используйте метод DOMDocument::createCDATASection() и добавьте его как любой другой узел.DOMNode::appendChild() возвращает добавленный узел, поэтому вы можете вкладывать вызовы:

$properties = [
   [ 'name' => 'qid', 'value' => "1"]
];

$document = new DOMDocument();
$subquestions = $document->appendChild(
    $document->createElement('subquestions')
);

// appendChild() returns the node, so it can be nested
$row = $subquestions->appendChild(
  $document->createElement('row')
);
// append the properties as element tiwth CDATA sections
foreach ($properties as $property) {
    $element = $row->appendChild(
        $document->createElement($property['name'])
    );
    $element->appendChild(
        $document->createCDATASection($property['value'])
    );
}

$document->formatOutput = TRUE;
echo $document->saveXML();

Вывод:

<?xml version="1.0"?>
<subquestions>
  <row> 
    <qid><![CDATA[1]]></qid>
  </row> 
</subquestions>

Использование обычных текстовых узлов работает лучше всего большую часть времени.

foreach ($properties as $property) {
    $element = $row->appendChild(
        $document->createElement($property['name'])
    );
    $element->appendChild(
        $document->createTextNode($property['value'])
    );
}

Это можно оптимизировать с помощью свойства DOMNode::$textContent.

foreach ($properties as $property) {
    $row->appendChild(
        $document->createElement($property['name'])
    )->textContent = $property['value'];
}
...