LIBXML_NOENT做了什么(为什么不称它为LIBXML_ENT)?

时间:2016-08-06 18:28:45

标签: php xml xml-parsing libxml2

在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

该标志似乎对预定义的实体(例如&lt;

)没有任何影响

所以我的问题是:

  • LIBXML_NOENT标志到底有什么作用?
  • 为什么叫LIBXML_NOENT?什么是简短的,而不是LIBXML_ENTLIBXML_PARSE_EXTERNAL_ENTITIES更合适?
  • 是否存在实际阻止解析所有实体的标志?

1 个答案:

答案 0 :(得分:3)

问: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,它会导致内部和外部实体的不同行为,因为后者无法加载。