【问题标题】:PHP DOMDocument: what is the nicest way to safely add text to an elementPHP DOMDocument:安全地将文本添加到元素的最佳方法是什么
【发布时间】:2015-04-05 16:06:19
【问题描述】:

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

我正在寻找一种使字符串 xml 安全的简洁方法——最好是利用 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>

【问题讨论】:

  • “比 preg_replace 或 htmlspecialchars 更好”——在哪些方面更好?
  • preg_replace 和 htmlspecialchars 是广谱工具。 preg_replace 方法完全取决于开发人员对 xml 字符问题的了解。 htmlspecialcharacters 接近seems to be disputed。由于这个问题是 XML 特有的,我希望 XML 库能够提供干净的方法来处理它。

标签: php xml special-characters domdocument


【解决方案1】:

这是我用来构建 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

【讨论】:

    【解决方案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>
    

    【讨论】:

    • 不幸的是,公平地说,documentation 也确实这样说:该值不会被转义。使用 DOMDocument::createTextNode() 创建一个支持转义的文本节点。
    猜你喜欢
    • 2019-08-24
    • 1970-01-01
    • 1970-01-01
    • 2011-11-21
    • 2011-09-17
    • 2018-08-10
    • 2022-01-18
    • 2011-07-28
    • 1970-01-01
    相关资源
    最近更新 更多