当声明源是参数实体替换文本时 XML 中相对 URI 的行为

Behavior of relative URIs in XML when declaration source is parameter entity replacement text

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

4.2.2 External Entities

[...]

[The location of the resource within which the entity declaration occurs] is defined to be the external entity containing the '<' which starts the declaration, at the point when it is parsed as a declaration.

A URI might thus be relative to the document entity, to the entity containing the external DTD subset, or to some other external parameter entity. [...]

初读时,我认为这两种说法是矛盾的。在我看来,任何文本的解析 “作为声明” 可能只发生在两种情况下:内部子集或外部子集。这似乎自然地遵循实体 dereferencing/expansion 是递归的事实。那么 "some other external parameter entity" 怎么可能成为 ID 的相关对象呢?

如果这两个陈述都是正确的,也许 "point when it is parsed" 这个短语并不代表我所理解的意思。此处的 "point" 是否可以指代定义源文本的任何上下文?

我将提供一个示例,可能有助于使这个问题更容易回答。

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

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 实体的绝对路径必须是 http://dotcom.xml/bar/baz/baz.ent.

这对我来说似乎很奇怪,因为外部参数实体的内容在文本声明之外只是一团文本,其上下文和含义直到后来(以及如果)在内部或外部子集。但这并不疯狂 — 足够简单地跟踪起源。

但是,为什么规范要用 "at the point when it is parsed" 来限定他们的声明?好吧,可能 this 是不同的:

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">

但这似乎行不通。我很确定现在说相对上下文不同是没有意义的,因为实体声明的 < 仍然是 "happened" in bar.ent。该规范特别指出了这一点。事实上,如果引用的位置很重要,那么它似乎必须始终是 http://dotcom.xml/baz/baz.ent,因为无论有多少中间参数实体,实际扩展都会在 foo.dtd 中发生 "back at home"在它和 baz.

之间

所以我想了解两件事:

  1. 以上,"baz/baz.ent"的正确绝对URL是什么?

  2. 一个。如果是 http://dotcom.xml/bar/baz/baz.ent,为什么规范说 "at the point where it is parsed"?

    b。如果是http://dotcom.xml/baz/baz.ent,为什么规范说"or to some other external parameter entity"?

Ouf,这是一个极端情况。我认为我们可以同意,您在哪里引用 %baz; 应该无关紧要。从。我很确定 "relative" 的意思应该是 "relative to the file in which the declaration appears"。因为我们很少听到关于一个 XML 处理器和另一个处理器之间的互操作的抱怨(是的),我敢打赌他们都做同样的事情,我希望就是这样。但是我没有测试过。

好问题。

与尊敬的 co-editor 不同,我认为这不是极端情况 全部;许多 public DTD 实例化了这种模式。但我确实认为 在像这样的正常情况下,大多数 XML 解析器都正确 回答。

首先,一些一般要点。

1 解析相对引用的一般原则 基本 URI 粗略地说,通常重要的基本 URI 是 使用相对引用的资源的基本 URI。

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

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

具体是什么类型的实体,我就不多说了 参考资料在什么时间处理,以及处理的动机 细节;简短的无动机的回答是,当 PE 引用是 在声明的替换文本中找到,它们将是 立即展开;当遇到一般实体引用时 (因为它们可能在另一个实体的替换文本中),它们是 不得扩大;它们在遇到时将被扩展 解析文档实例,但在解析 DTD 时不解析。

First, our document. This could be anywhere, since the external DTD it references uses an absolute URL for a system ID.

FILE: doc.xml

当我们开始处理这个文件时,

形式的条目
  • #document "file://Users/semicolon/docs/doc.xml"

被压入实体栈,任何相关的基础URI 决议是 "file://Users/semicolon/docs/doc.xml".

well-formedness XML 规则的一个结果是,当我们 读完那个实体,堆栈变空,XML 文档结束。

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

So next up is the DTD — unambiguously to be found at http://dotcom.xml/foo.dtd:

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

一旦我们开始解析这个外部子集,实体堆栈就会看起来 像这样:

并且在相对引用解析中使用的基本 URI 是 “http://dotcom.xml/foo.dtd”。

N.B。严格来说,现在堆栈中的两个实体都是 匿名的;为了方便起见,我给他们起了以“#”开头的名字(为了 避免与命名实体可能发生的冲突),但这只是为了 方便,因为在 错误消息比“您从 SYSTEM 指向的那个资源 文档类型声明中的标识符。”

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

Still nothing ambiguous. It’s clear that our next resource is to be found at http://dotcom.xml/bar/bar.ent

好吧,取决于你所说的 "next" 是什么意思,这要么是正确的,要么 错误的。如果您的意思是“在我们处理 http://dotcom.xml/foo.dtd 之后,我们 然后处理http://dotcom.xml/bar/bar.ent”,则为假。 文件 .../bar.ent 在 处理期间 处理 .../foo.dtd, 不之后。如果你的意思是“下一个实体被推到实体上 堆栈是 PE 'bar'",那么它是真的。

如果您显示的两行是文件 "foo.dtd" 的开头,并且 后面跟着进一步的声明,PE 'bar' 必须被解析并且 在 之前 处理以下声明。就算什么都没有 遵循 PE 参考 %bar;但空格或 EOF,严格来说 说到外部参数实体 'bar' 应该被处理 当对它的引用被识别时,因此在 遇到以下 EOF。

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

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

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

并且解决方案的基本 URI 是 http://dotcom.xml/bar/bar.ent

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

But here’s where I get unsure. Given that the spec specifically states that it is possible for a path to be relative to an external parameter entity, the only thing I can think of is that here, the absolute path for the baz entity must be http://dotcom.xml/bar/baz/baz.ent.

是的。

This seemed odd to me because the content of an external parameter entity is, beyond the text declaration, just a blob of text whose context and meaning is unknowable until later, when (and if) it is referenced in either an internal or external subset. But it’s not crazy — keeping track of the origin in simple enough.

对于 parameter-entity 引用,没有 "later" 你的意思 意思是,我想。 (我当然可能误解你。)参考是 在识别点扩展和解析。而且无论如何, 在示例中,'bar' 和 'baz' 都在 中被引用 外部子集。但是您从 XML 规范中引用的规则具有 结果是任何外部参数实体的绝对 URI 是 原则上定义明确,无论是否提及。

But why, then, does the spec qualify their statement with "at the point when it is parsed"? Well, it could be that this is different:

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">

But that doesn’t seem to work. I’m pretty sure it doesn’t make sense to say that the relative context is different now, because the entity declaration’s < still "happened" in bar.ent. The spec specifically calls that point out.

同意(我认为)。

In fact, if the location of the reference mattered, then it would seem to have to always be http://dotcom.xml/baz/baz.ent, since the actual expansion takes place "back at home" in foo.dtd no matter how many intermediate parameter entities there are between it and baz.

不,PE 引用的扩展会立即发生,'in' 遇到它们的实体。没关系任何事物 但可能会出现错误消息和相对引用的绝对化,但很清楚。

对"the point when [the PE declaration] is parsed"的引用是 旨在涵盖以下情况。在一个参数实体 A 我们有一个形式的声明

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

这不是参数实体的声明'chapters',而是 参数实体 'chapdecl' 的声明包含 'chapters'.

声明

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

%chapdecl;

我读规范告诉我们相对参考 "chapters.dtd" 是相对于 B 的基础 URI,而不是 A。

看到几年前我得出了同样的结论,我感到欣慰 在 http://cmsmcq.com/mib/?p=1289(虽然我正在工作的程序 然后在这个极端情况下做了错误的事情)。

So I’m looking to understand two things:

Above, what is the correct absolute URL for "baz/baz.ent"?

a. If it is http://dotcom.xml/bar/baz/baz.ent, why does the spec says "at the point where it is parsed"?

是的。

规范说明了它试图做什么(显然不是 完全成功)以明确相关的基础 URI 是 包含声明 D 的实体 E 包含 "baz/baz.ent" 的相对引用 R。

略显繁琐的措辞也是想表达(我认为) 在异常(或病态)情况下,如上面的 A/B 情况,其中 看起来像 PE 声明的实际字符串出现在一个实体中 并且解析规则表明它被识别并处理为 PE 在另一个实体中声明,它是后一个实体(B 例如)使用其基本 URI,而不是包含字符串的 URI (一种)。 A 包含一个 看起来 像声明的字符串; B包含 (通过 'chapdecl' 的扩展)声明。 (严格来说 也就是说,声明时实体堆栈上的顶部实体 遇到的是 'chapdecl',但它不是外部实体,所以它 不算。)

如果有帮助,句子中'it'的先行词是 'declaration',我们正在谈论的是 声明被解析,而不是实体的替换点 文本被解析。

b. If it is http://dotcom.xml/baz/baz.ent, why does the spec say "or to some other external parameter entity"?

不是,规范说“或其他一些外部参数 entity" 部分以明确它不是。