当声明源是参数实体替换文本

时间:2017-02-12 07:09:44

标签: xml xml-parsing specifications dtd

我正在尝试了解相对系统ID URI的正确行为。首先,让我引用规范:

  

4.2.2外部实体

     

[...]

     

[发生实体声明的资源的位置]被定义为包含'<'的外部实体。它在声明为声明的时候开始声明。

     因此,URI可能相对于文档实体,包含外部DTD子集的实体或某些其他外部参数实体。 [...]

在一读时,我认为这两个陈述是矛盾的。在我看来,任何文本“作为声明”的解析可能只发生在两个上下文中:内部子集或外部子集。这似乎自然地来自实体解除引用/扩展是递归的事实。那么“其他一些外部参数实体”怎么能成为ID相对的呢?

对于两个陈述都是真的,也许短语“解析时的点”并不意味着我所说的意思。这里的“点”可以指代源文本定义的任何上下文吗?

我将提供一个可能有助于使这个问题更加紧迫的问题的例子。

首先,我们的文件。这可以是任何地方,因为它引用的外部DTD使用系统ID的绝对URL。

FILE: doc.xml

    <!DOCTYPE foo SYSTEM "http://dotcom.xml/foo.dtd">
    ...

接下来是DTD - 明确地在http://dotcom.xml/foo.dtd找到:

FILE: http://dotcom.xml/foo.dtd

    <!ENTITY % bar SYSTEM "bar/bar.ent">
    %bar;

仍然没有任何暧昧。很明显,我们的下一个资源可以在http://dotcom.xml/bar/bar.ent

找到
FILE: http://dotcom.xml/bar/bar.ent

    <!ENTITY % baz SYSTEM "baz/baz.ent">
    %baz;

但这是我不确定的地方。鉴于规范明确指出路径可能相对于外部参数实体,我唯一能想到的是,baz实体的绝对路径必须是{{1} }。

这对我来说似乎很奇怪,因为除了文本声明之外,外部参数实体的内容只是一个文本的blob,其上下文和含义在以后,当(以及如果)在内部或者内部引用时是不可知的外部子集。但这并不疯狂 - 足够简单地跟踪起源。

但是,为什么规范是否会在“解析时”对其声明进行限定?好吧,可能是这个是不同的:

http://dotcom.xml/bar/baz/baz.ent

但这似乎不起作用。我很确定现在说相对上下文不同是没有意义的,因为FILE: http://dotcom.xml/foo.dtd <!ENTITY % bar SYSTEM "bar/bar.ent"> %bar; %baz; FILE: http://dotcom.xml/bar/bar.ent <!ENTITY % baz SYSTEM "baz/baz.ent"> 中的实体声明<仍然“发生”。该规范特别指出了这一点。实际上,如果引用的位置很重要,那么它似乎必须始终为bar.ent,因为无论有多少中间参数实体,实际扩展都会在http://dotcom.xml/baz/baz.ent中“返回主页”进行它与foo.dtd之间存在。

所以我想了解两件事:

  1. 上面,baz的正确绝对网址是什么?

  2. 一个。如果是"baz/baz.ent",为什么规范说“在解析它的位置”?

    湾如果是http://dotcom.xml/bar/baz/baz.ent,为什么规范说“或者其他一些外部参数实体”?

2 个答案:

答案 0 :(得分:2)

不错的问题。

与我尊敬的共同编辑不同,我不认为这是一个极端的案例 所有;许多公共DTD实例化这种模式。但我确实认为 在像这样的正常情况下,大多数XML解析器都是正确的 答案。

首先,一些一般性观点。

1解决相对引用的一般原则 一般来说,基本URI通常是计算的基URI 使用相对引用的资源的基URI。

2 XML规范的工作是说明对亲戚意味着什么 在实体声明中找到的资源是&#34;使用&#34;在相关的 感觉,以及在哪里寻找合适的基URI。规范 答案在你引用的段落中给出。这相当于说 参数实体声明时,相对引用是使用 包含它被解析为参数实体声明,而不是 在其他时间,要使用的基URI是。的基URI PE声明发生的实体。

3因为你观察到PE引用是递归扩展的,所以 PE引用的集合在任何给定点扩展 解析由堆栈建模。任何给定亲属的基URI reference是堆栈顶部的外部实体的URI 当解析包含该相对引用的声明时。

我会默默地通过什么类型的实体的细节 参考是在什么时间处理,以及动机 细节;简短无心的回答是,当PE引用时 在声明的替换文本中找到,它们是 立即扩大;何时遇到通用实体引用 (因为它们可能在另一个实体的替换文本中),它们是 不被扩大;遇到它们时要扩大它们 解析文档实例,但不解析DTD。

  

首先,我们的文件。这可能是任何地方,因为外部   它引用的DTD使用系统ID的绝对URL。

     

FILE:doc.xml

当我们开始处理此文件时,表单

的条目
  • #document&#34; file://Users/semicolon/docs/doc.xml"

被推送到实体堆栈,以及任何相关的基本URI 分辨率为&#34; file://Users/semicolon/docs/doc.xml"。

XML的良构性规则的一个结果就是我们 读完该实体并且堆栈变空,即XML 文件结束了。

    <!DOCTYPE foo SYSTEM "http://dotcom.xml/foo.dtd">
    ...
  

接下来是DTD - 毫不含糊地发现了   http://dotcom.xml/foo.dtd

     

文件:http://dotcom.xml/foo.dtd

一旦我们开始解析这个外部子集,实体堆栈就会显示出来 像这样的东西:

和相对参考分辨率中使用的基URI是 &#34; http://dotcom.xml/foo.dtd&#34;

N.B。现在堆栈中的两个实体都严格来说 匿名;为方便起见,我给他们起了名字#&#39;#&#39; (至 避免与命名实体发生冲突),但这只是为了 方便,因为它更容易引用#dtd-external&#39;在一个 错误消息而不是&#34;您从SYSTEM指向的资源 文档类型声明中的标识符。&#34;

    <!ENTITY % bar SYSTEM "bar/bar.ent">
    %bar;
  

仍然没有任何暧昧。很明显,我们的下一个资源是   可以在http://dotcom.xml/bar/bar.ent

找到

那么,取决于你的意思&#34; next&#34;,这是真的还是 假。如果您的意思是&#34;在我们处理http://dotcom.xml/foo.dtd之后,我们 然后处理http://dotcom.xml/bar/bar.ent,&#34;那是假的。该 处理... / foo.dtd期间处理文件... / bar.ent, 不是之后。如果你的意思是&#34;下一个要推到实体上的实体 堆栈是PE&#39;&#39;&#34;&#34;&#34;&#34;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39

如果您显示的两行是文件&#34; foo.dtd&#34;的开头,并且 接下来是进一步的声明,PE&#39; bar&#39;必须解析和 在之后处理以下声明。即使没有 遵循PE参考%bar;但严格地说是空白或EOF 说外部参数实体&#39; bar&#39;应该处理 当识别出对它的引用时,立即识别它 遇到以下EOF。

但我同意相对参考的正确解决方案是 您指定的绝对引用。

  

文件:http://dotcom.xml/bar/bar.ent

一旦我们开始阅读这个实体,实体堆栈就是:

,解析的基本URI为http://dotcom.xml/bar/bar.ent

    <!ENTITY % baz SYSTEM "baz/baz.ent">
    %baz;
  

但这是我不确定的地方。鉴于具体规格   声明路径可能是相对于   外部参数实体,我唯一能想到的是   这里,baz实体的绝对路径必须是   http://dotcom.xml/bar/baz/baz.ent

  

这对我来说似乎很奇怪,因为外部参数的内容       除了文本声明之外,实体只是一个文本块       语境和意义是不可知的,直到以后,何时(如果)       在内部或外部子集中引用。但事实并非如此       疯狂 - 简单地跟踪起源。

对于参数实体引用,没有&#34;以后&#34;在某种意义上你 我想是的意思是。 (我当然可能会误解你。)参考文献是 在识别时扩展和解析。无论如何, 在示例中,&#39; bar&#39;和&#39;巴兹&#39; 在中被引用 外部子集。但是你引用XML规范的规则有 结果是任何外部参数实体的绝对URI是 原则上定义明确,无论是否提及。

  

但是,那么为什么规范会使用&#34;来证明他们的声明       在解析时指出&#34;?好吧,可能就是这样       不同:

     

文件:http://dotcom.xml/foo.dtd

    <!ENTITY % bar SYSTEM "bar/bar.ent">
    %bar;
    %baz;
  

文件:http://dotcom.xml/bar/bar.ent

   <!ENTITY % baz SYSTEM "baz/baz.ent">
  

但这似乎不起作用。我很确定它没有       意思是说现在相对背景不同,因为       实体声明&lt;仍然&#34;发生了#34;在bar.ent。规范       特别要求指出。

同意(我认为)。

  事实上,如果的位置       参考重要,然后它似乎必须永远       http://dotcom.xml/baz/baz.ent,因为实际扩展需要       地点&#34;回到家里&#34;在foo.dtd中,无论中间有多少       参数实体介于它和baz之间。

不,PE参考的扩展立即发生,&#39;在&#39;该 遇到他们的实体。这对任何事情都无关紧要 但错误信息和相对参考文献的绝对化,也许,但它很清楚。

引用&#34;解析[PE声明]的时间点&#34;是 旨在涵盖以下情况。在一个参数实体A中 我们有一份表格的声明

<!ENTITY % chapdecl '&#x003C;!ENTITY % chapters SYSTEM "chapters.dtd">'>  

这不是参数实体&#39;章节的声明,而是 声明参数实体&quot; chapdecl&#39;含有 声明&#39;章节&#39;。

在另一个参数实体B中,遇到并处理 稍后,我们有参数实体引用

%chapdecl;

我读了规范,告诉我们相对参考 &#34; chapters.dtd&#34;是相对于B的基URI而不是A。

我很欣慰地看到几年前我得出了同样的结论 在http://cmsmcq.com/mib/?p=1289(虽然我正在开展这项计划 然后在这个角落的情况下做错了。)

  

所以我想了解两件事:

     

上面,&#34; baz / baz.ent&#34;的正确绝对网址是什么?

     

一个。如果是http://dotcom.xml/bar/baz/baz.ent,为什么规范       说&#34;在解析它的时候&#34;?

是的。

规范说出它在尝试中做了什么(显然不是 完全成功)明确相关的基本URI 包含声明D的实体E的包含 相对参考R到&#34; baz / baz.ent&#34;。

稍微麻烦的措辞也试图说(我认为) 在异常(或病态)案件中,如上面的A / B案例,其中 看起来像PE声明的实际字符串出现在一个实体中 并且解析规则表明它被识别并作为PE进行处理 在另一个实体中的声明,它是后一个实体(B中的 示例)使用其基URI,而不是包含该字符串的URI (一个)。 A包含一个看起来的字符串,如声明; B包含 (通过扩展&#39; chapdecl&#39;)声明。 (严格 说,声明时实体堆栈上的顶级实体 遇到的是&#39; chapdecl&#39;,但它不是外部实体所以它 不算数。)

如果它有所帮助,那么它的前提是“它”。在这句话中 &#39;声明&#39;,我们正在谈论的重点 声明被解析,而不是实体的替换点 文本被解析。

  

湾如果是http://dotcom.xml/baz/baz.ent,为什么规范会说       &#34;或其他一些外部参数实体&#34;?

不是,规范说&#34;或其他一些外部参数 实体&#34;部分是为了表明它不是。

答案 1 :(得分:1)

Ouf,这是一个角落案例。我想我们可以同意你在哪里提到%baz并不重要;从。我很确定意图是“相对”应该表示“相对于声明出现的文件”。因为我们很少从未听过有关一个XML处理器与另一个XML处理器之间互操作的抱怨(Yay),我敢打赌他们都做同样的事情,我希望它就是这样。但我还没有测试过。