PHP DOMDocument:安全地向元素添加文本的最佳方式是什么
PHP DOMDocument: what is the nicest way to safely add text to an element
添加可能包含麻烦字符(例如 &、<、>)的字符串时,DOMDocument 会抛出警告,而不是清理字符串。
我正在寻找一种使字符串 xml 安全的简洁方法 - 最好是利用 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>
您将必须创建文本节点并附加它。我在这个答案中描述了这个问题:
但是您可以扩展 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 & Son</bar>
<bar xmlns="urn:bar">Company & Son</bar>
</foo>
这是我用来构建 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
添加可能包含麻烦字符(例如 &、<、>)的字符串时,DOMDocument 会抛出警告,而不是清理字符串。
我正在寻找一种使字符串 xml 安全的简洁方法 - 最好是利用 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>
您将必须创建文本节点并附加它。我在这个答案中描述了这个问题:
但是您可以扩展 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 & Son</bar>
<bar xmlns="urn:bar">Company & Son</bar>
</foo>
这是我用来构建 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