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

标签 xml xml-parsing specifications dtd

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


4.2.2外部实体

[...]

[将发生实体声明的资源的位置]定义为包含“ <”的外部实体,该外部实体在将其解析为声明时开始声明。

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


一读时,我认为这两个说法是矛盾的。在我看来,“作为声明”的任何文本解析都只能在两个上下文中进行:内部子集或外部子集。这似乎是由于实体解除引用/扩展是递归的事实而产生的。那么“某个其他外部参数实体”怎么可能是ID相对的呢?

对于这两种说法都是正确的,也许短语“解析时指向”不代表我的意思。这里的“点”是否可以引用定义了源文本的任何上下文?

我将提供一个示例,该示例可能有助于使这个问题更加迫在眉睫。

首先,我们的文件。它可以在任何地方,因为它引用的外部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

在我看来,这很奇怪,因为外部参数实体的内容(除了文本声明之外)只是一小段文本,其上下文和含义在以后(以及(如果)在内部或外部子集中被引用时)才是未知的。但这并不疯狂-只需简单地跟踪起源即可。

但是,为什么规范会用“解析时的点”来限定其声明呢?好吧,这可能是不同的:

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"的正确绝对URL是什么?
一个。如果是http://dotcom.xml/bar/baz/baz.ent,为什么规范会说“在解析点”?

b。如果是http://dotcom.xml/baz/baz.ent,为什么规范会说“或其他外部参数实体”?

最佳答案

好问题。

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

首先,一些一般要点。

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

2 XML规范的工作是说它对亲戚意味着什么
实体声明中发现的资源将在相关
意识,以及在哪里寻找适当的基本URI。规格的
您引用的段落中给出了答案。等于说
参数实体声明时使用相对引用
包含它的内容将解析为参数实体声明,而不是
在其他时间,要使用的基本URI是
PE声明所在的实体。

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

我将默默地介绍什么样的实体的细节
参考文件在什么时间处理,以及
细节;简短而无动机的答案是,当PE参考是
在声明的替代文本中找到的
立即扩展;遇到通用实体引用时
(因为它们可能在另一个实体的替换文本中),它们是
不扩大;它们在遇到时将被扩展
解析文档实例,但不解析DTD时。


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

文件:doc.xml


当我们开始处理此文件时,输入以下形式


#document“ file://Users/semicolon/docs/doc.xml”


被推送到实体堆栈上,并且任何内容的相关基本URI
分辨率为“ 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


一旦我们开始解析此外部子集,实体堆栈将看起来
像这样的东西:


#dtd-externalhttp://dotcom.xml/foo.dtd
#document“ file://Users/semicolon/docs/doc.xml”


相对参考解析中使用的基本URI为
http://dotcom.xml/foo.dtd”。

N.B.严格来说,堆叠中的两个实体
匿名;为了方便起见,我给他们起了以“#”开头的名称(
避免与命名实体发生冲突),但这仅用于
方便,因为在其中更容易引用“#dtd-external”
错误消息,而不是“您从SYSTEM指向的资源
文档类型声明中的标识符。”

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



仍然没有任何歧义。很明显,我们的下一个资源是
http://dotcom.xml/bar/bar.ent处找到


好吧,取决于您对“下一个”的含义,是真的还是
假。如果您的意思是“在我们处理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。

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


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


一旦我们开始阅读此实体,该实体堆栈即为:


barhttp://dotcom.xml/bar/bar.ent
#dtd-externalhttp://dotcom.xml/foo.dtd
#document“ 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


是。


这在我看来很奇怪,因为外部参数的内容
实体,除了文字声明之外,只是一小段文字,
直到后来,当(如果)
在内部或外部子集中引用。但这不是
疯狂的-足够简单地跟踪起源。


对于参数实体引用,在您的意义上没有“后”
我是说(我当然会误解您。)参考是
在识别点扩展和解析。而且无论如何
在示例中,“ bar”和“ baz”都已在
外部子集。但是您从XML规范中引用的规则具有
结果是任何外部参数实体的绝对URI为
原则上定义明确,无论是否引用。


但是,为什么规范会用“在
点何时被解析”?嗯,可能是
不同:

文件: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">



但这似乎不起作用。我很确定这不会
说相对的上下文现在有所不同,是因为
实体声明的<仍然在bar.ent中“发生”。规格
明确指出这一点。


同意(我认为)。


其实,如果位置
参考很重要,那么似乎总是
http://dotcom.xml/baz/baz.ent,因为实际的扩展需要
不管有多少中间,都将“回到家里”放在foo.dtd中
它和baz之间存在参数实体。


不,PE参考的扩展会立即在
遇到它们的实体。没关系
但是可能会出现错误消息和相对引用的绝对化,但这很明显。

对“ [PE声明]的解析点”的引用是
旨在涵盖以下情况。在一个参数实体A中
我们有一个形式的声明

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


这不是参数实体“章节”的声明,而是
包含以下内容的参数实体“ chapdecl”的声明
声明“章节”。

在另一个参数实体B中,遇到并处理它
以后,我们有参数实体参考

%chapdecl;


我阅读该规范是为了告诉我们相对参考
“ chapters.dtd”是相对于B而不是A的基本URI。

看到几年前我得出相同的结论,我感到很高兴
http://cmsmcq.com/mib/?p=1289(尽管我正在使用该程序
则在这种情况下会做错事)。


因此,我希望了解两件事:

上方,“ baz / baz.ent”的正确绝对URL是什么?

一个。如果是http://dotcom.xml/bar/baz/baz.ent,为什么要指定
说“在解析点”?


它是。

规格说明了尝试进行的操作(显然不是
完全成功)以明确相关的基本URI是
包含声明D的实体E的实体,声明D包含
相对参考R到“ baz / baz.ent”。

稍微麻烦的措词也试图说(我认为)
在异常(或病理性)情况下,例如上述A / B情况,
看起来像PE声明的实际字符串出现在一个实体中
并且解析规则说它被识别为PE
另一个实体中的声明,则是后者(
例如)使用其基本URI,而不是包含字符串的URI
(一个)。包含看起来像声明的字符串; B包含
(通过扩展“ chapdecl”)声明。 (严格
讲,当声明为
遇到的是“ chapdecl”,但它不是外部实体,因此
不算在内。)

如果有帮助,句子中“ it”的前身是
“声明”,我们正在谈论的是
解析声明,而不是实体的替换点
文本被解析。


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


并非如此,规范说“或其他一些外部参数
实体”部分,以表明并非如此。

关于xml - 当声明源是参数实体替换文本时,XML中相对URI的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42185078/

相关文章:

java - 使用 Jackson 反序列化 XML 以从 XSD 生成选择时出错

java - 删除xml文件中字符串前后不需要的字符串

c - EZXML C 解析 API

macros - RPM 规范中的 `%setup -q` 是什么?

C 原型(prototype)范围

html - 无法在 IE10 上获得同源 iframe 主体?

Python 将 unicode 保存到 XML

java - JAXB 编码器初始化

jquery - 如何在 Chrome 24 和 jQuery 1.8.2 中解析命名空间 XML?

java - 使用 XSLT 为所有节点生成 XML 的 xpath