PHP DOMDocument:安全地向元素添加文本的最好方法是什么

时间:2015-02-05 17:16:58

标签: php xml special-characters domdocument

添加可能包含麻烦字符的字符串(例如&,<,>)时,DOMDocument会抛出警告,而不是清理字符串。

我正在寻找一种简洁的方法来使字符串xml-safe - 理想情况下利用DOMDocument库。

我正在寻找比preg_replacehtmlspecialchars更好的东西。我看到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>

2 个答案:

答案 0 :(得分:2)

您必须创建文本节点并附加它。我在这个答案中描述了问题:https://stackoverflow.com/a/22957785/2265374

但是,您可以延长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>

答案 1 :(得分: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