ID 解析有最低 DTD


There are a minimal DTD for ID resolution?

我想通过一个丑陋的黑客来解决这个问题:向我的"任何XML"声明一个"假DTD"......举个例子解释:

输入(任何 XML 片段(

<root id="root">
  <p id="p1"><i>Title</i></p>
  <p id="p2"><b id="b1">AAA<sup>1</sup>, BBB<sup>2</sup></b></p>
</root>

PHP代码,

   $DTD = '
   <!DOCTYPE noname [
   <!ATTLIST ANY
      id     ID             #IMPLIED
   >
   ]>';
   $dom = new DomDocument();
   $dom->loadXML( "$DTD'n$input" );
   $e = $dom->getElementById('p1');
   var_dump($e);

这段代码不是解决方案:$e是空的,我不明白为什么......那么,问题来了:是否有可能表达解决这个问题的"最小DTD"?

如果您只想使 ID 机制正常工作,最简单的选择是使用 xml:id

<root xml:id="root">
  <p xml:id="p1"><i>Title</i></p>
  <p xml:id="p2"><b xml:id="b1">AAA<sup>1</sup>, BBB<sup>2</sup></b></p>
</root>

根据 https://fosswiki.liip.ch/display/BLOG/GetElementById+Pitfalls 的说法,xml:id应该在PHP中使用getElementById


您的尝试问题:

  1. <!DOCTYPE后面的元素名称必须与 XML 文档的根元素的名称匹配。在您的情况下,noname != root ,这不起作用。请参阅 http://www.w3.org/TR/xml/#sec-prolog-dtd。

  2. 必须为每个元素声明属性。不能声明 ANY 的属性。即使元素的内容模型是ANY的,你仍然必须声明所有可能发生的元素。

因此,无法仅为 ID 解析创建 DTD。以下内容进行验证,并且它实际上不能小于此值:

<!DOCTYPE root [
<!ELEMENT root (p+)>
<!ATTLIST root
         id  ID   #IMPLIED>
<!ELEMENT p ANY>
<!ATTLIST p
         id  ID   #IMPLIED>
<!ELEMENT b ANY>
<!ATTLIST b
         id  ID   #IMPLIED>
<!ELEMENT sup (#PCDATA)>
<!ELEMENT i (#PCDATA)>
]>
<root id="root">
  <p id="p1"><i>Title</i></p>
  <p id="p2"><b id="b1">AAA<sup>1</sup>, BBB<sup>2</sup></b></p>
</root>

只要 XML 分析器不尝试验证,就可以提供较小的 DTD。此文档在非验证模式下被 xmllint(和 PHP(接受:

<!DOCTYPE anyname [ 
<!ATTLIST p id ID #IMPLIED> 
]>
<root id="root">
  <p id="p1"><i>Title</i></p>
  <p id="p2"><b id="b1">AAA<sup>1</sup>, BBB<sup id="b1">2</sup></b></p>
</root>

并报告p元素上的 ID 唯一性违规。

如果使用 --postvalid 选项运行 xmllint(或者在启用 LIBXML_DTDVALID 的情况下运行 PHP(,则会发出以下命令:

test.xml:4: element root: validity error : root and DTD name do not match 'root' and 'anyname'