PHP DOMDocument: какой самый хороший способ безопасно добавить текст в элемент

0

При добавлении строки, которая может содержать неприятные символы (например, &, <,>), DOMDocument выдает предупреждение, а не санирует строку.

Я ищу краткий способ сделать строки xml-safe - в идеале, что-то, что использует библиотеку DOMDocument.

Я ищу что-то лучшее, чем preg_replace или htmlspecialchars. Я вижу DOMDocument::createTextNode(), но полученный объект DOMText является громоздким и не может быть передан DOMDocument::createElement().

Чтобы проиллюстрировать проблему, этот код:

<?php 

$dom = new DOMDocument;
$dom->formatOutput = true;
$parent = $dom->createElement('rootNode');
$parent->appendChild( $dom->createElement('name', 'this ampersand causes pain & sorrow ') );
$dom->appendChild( $parent );
echo $dom->saveXml();

производит этот результат (см. eval.in):

Warning: DOMDocument::createElement(): unterminated entity reference          sorrow in /tmp/execpad-41ee778d3376/source-41ee778d3376 on line 6
<?xml version="1.0"?>
<rootNode>
  <name>this ampersand causes pain </name>
</rootNode>
  • 0
    «Лучше, чем preg_replace или htmlspecialchars» - лучше в каком отношении?
  • 0
    preg_replace и htmlspecialchars являются инструментами широкого спектра. Подход preg_replace полностью зависит от знания разработчиком проблем с символами XML. Подход htmlspecialcharacters, кажется, оспаривается . И поскольку эта проблема присуща XML, я ожидаю, что библиотека XML предоставит четкие способы решения этой проблемы.
Теги:
special-characters
domdocument

2 ответа

2
Лучший ответ

Вам нужно будет создать текстовый узел и добавить его. Я описал проблему в этом ответе: qaru.site/questions/812278/...

Однако вы можете расширить DOMDocument и перегрузить createElement*().

class MyDOMDocument extends DOMDocument {

  public function createElement($name, $content = '') {
    $node = parent::createElement($name);
    if ((string)$content !== '') {
      $node->appendChild($this->createTextNode($content));
    }
    return $node;
  }

  public function createElementNS($namespace, $name, $content = '') {
    $node = parent::createElementNS($namespace, $name);
    if ((string)$content !== '') {
      $node->appendChild($this->createTextNode($content));
    }
    return $node;
  }
}

$dom = new MyDOMDocument();
$root = $dom->appendChild($dom->createElement('foo'));
$root->appendChild($dom->createElement('bar', 'Company & Son'));
$root->appendChild($dom->createElementNS('urn:bar', 'bar', 'Company & Son'));

$dom->formatOutput = TRUE;
echo $dom->saveXml();

Вывод:

<?xml version="1.0"?>
<foo>
  <bar>Company &amp; Son</bar>
  <bar xmlns="urn:bar">Company &amp; Son</bar>
</foo>
  • 0
    И, к сожалению, чтобы быть справедливым, документация также говорит об этом: значение не будет экранировано. Используйте DOMDocument :: createTextNode () для создания текстового узла с экранирующей поддержкой.
  • 1
    Записка не совсем правильная: она ускользает, просто не все: eval.in/278921
0

Это структура, которую я использую для создания элементов XML, вторая часть обычно завернута в функцию.

$parent = $document->documentElement; // pick the node we want to append to
$name = 'foo'; // new element name
$content = 'bar < not a tag > <![CDATA[" testing cdata "]]>'; // content

$element = ($parent->ownerDocument) ? $parent->ownerDocument->createElement($name) : $parent->createElement($name);
$parent->appendchild($element);
$element->appendchild($parent->ownerDocument->createTextNode($content));

моя функция return $element

Ещё вопросы

Сообщество Overcoder
Наверх
Меню