我正在尝试了解相对系统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
之间存在。
所以我想了解两件事:
上面,baz
的正确绝对网址是什么?
一个。如果是"baz/baz.ent"
,为什么规范说“在解析它的位置”?
湾如果是http://dotcom.xml/bar/baz/baz.ent
,为什么规范说“或者其他一些外部参数实体”?
答案 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:
一旦我们开始解析这个外部子集,实体堆栈就会显示出来 像这样的东西:
#dtd-external
&#34; http://dotcom.xml/foo.dtd&#34; #document
&#34; file://Users/semicolon/docs/doc.xml" 和相对参考分辨率中使用的基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;必须解析和
在
但我同意相对参考的正确解决方案是 您指定的绝对引用。
一旦我们开始阅读这个实体,实体堆栈就是:
bar
&#34; http://dotcom.xml/bar/bar.ent&#34; #dtd-external
&#34; http://dotcom.xml/foo.dtd&#34; #document
&#34; file://Users/semicolon/docs/doc.xml" ,解析的基本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;?好吧,可能就是这样 不同:
<!ENTITY % bar SYSTEM "bar/bar.ent">
%bar;
%baz;
<!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 '<!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),我敢打赌他们都做同样的事情,我希望它就是这样。但我还没有测试过。