【问题标题】:What does LIBXML_NOENT do (and why isn't it called LIBXML_ENT)?LIBXML_NOENT 做什么(为什么不叫 LIBXML_ENT)?
【发布时间】:2016-12-12 22:44:48
【问题描述】:

在 PHP 中,可以将可选参数传递给各种 XML 解析器,其中之一是 LIBXML_NOENTdocumentation 对此有话要说:

LIBXML_NOENT(整数)
替代实体

Substitute entities 信息量不是很大(什么实体?它们何时被替换?)。但我认为假设NOENTNO_ENTITIESNO_EXTERNAL_ENTITIES 的缩写是公平的,所以对我来说,这个标志禁用(外部)实体的解析似乎是一个公平的假设。

但确实不是这样的:

$xml = '<!DOCTYPE root [<!ENTITY c PUBLIC "bar" "/etc/passwd">]>
<test>&c;</test>';
$dom = new DOMDocument();
$dom->loadXML($xml, LIBXML_NOENT);
echo $dom->textContent;

结果是回显了/etc/passwd 的内容。如果没有 LIBXML_NOENT 参数,情况并非如此。

对于非外部实体,该标志似乎没有任何作用。示例:

$xml = '<!DOCTYPE root [<!ENTITY c "TEST">]>
<test>&c;</test>';
$dom = new DOMDocument();
$dom->loadXML($xml);
echo $dom->textContent;

这段代码的结果是“TEST”,有和没有LIBXML_NOENT

该标志似乎对&amp;lt;等预定义实体没有任何影响。

所以我的问题是:

  • LIBXML_NOENT 标志具体有什么作用?
  • 为什么叫LIBXML_NOENT?它的缩写是什么,LIBXML_ENTLIBXML_PARSE_EXTERNAL_ENTITIES 不是更合适吗?
  • 是否存在实际上阻止解析所有实体的标志?

【问题讨论】:

  • 它是mapped to libxml 常量XML_PARSE_NOENT,如果它可以为您提供任何搜索。描述的很模糊……

标签: php xml xml-parsing libxml2


【解决方案1】:

问:LIBXML_NOENT 标志到底有什么作用?

该标志允许替换 XML 字符实体引用,无论是否外部。

问:为什么叫LIBXML_NOENT?它的缩写是什么,LIBXML_ENT 或 LIBXML_PARSE_EXTERNAL_ENTITIES 不是更合适吗?

这个名字确实具有误导性。我认为NOENT只是意味着解析文档的节点树不会包含任何实体节点,因此解析器将替换实体。如果没有NOENT,解析器会为实体引用创建DOMEntityReference 节点。

问:是否存在实际上阻止解析所有实体的标志?

LIBXML_NOENT 启用所有实体引用的替换。如果您不想扩展实体,只需省略该标志即可。例如

$xml = '<!DOCTYPE test [<!ENTITY c "TEST">]>
<test>&c;</test>';
$dom = new DOMDocument();
$dom->loadXML($xml);
echo $dom->saveXML();

打印

<?xml version="1.0"?>
<!DOCTYPE test [
<!ENTITY c "TEST">
]>
<test>&c;</test>

似乎textContent 会自行替换实体,这可能是 PHP 绑定的一个特性。如果没有LIBXML_NOENT,它会导致内部和外部实体的行为不同,因为后者不会被加载。

【讨论】:

  • 感谢您的回答!在您对第三个问题的回答中,您的意思是 enables 而不是 disables,对吧?有没有办法在不解析实体的情况下访问 DOM?因为不仅仅是textContent 做到了,它也是$dom-&gt;getElementsByTagName('test')-&gt;item(0)-&gt;nodeValue。如果我做print_r($dom-&gt;childNodes-&gt;item(1));,它似乎也总是被解析,内部实体没有DOMEntityReference。但是对于外部实体,LIBXML_NOENT 在这里有所不同。 saveXML 的输出确实不同,即使对于内部实体也是如此。
  • @tim 我修正了第三个问题的答案。 nodeValuetextContent 通常是相同的。要访问DOMEntityReference 节点,请尝试$dom-&gt;documentElement-&gt;childNodes-&gt;item(0)$dom-&gt;documentElement-&gt;firstChild
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-08-17
  • 2014-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-09
  • 2018-07-13
相关资源
最近更新 更多