[/*SemanticWeb*/][转]将XML文档与XInclude 合并在一起 |
nybon 发表于 2004/12/23 8:21:00 |
将 XML 文档与 XInclude 合并在一起
发布日期: 5/20/2004 | 更新日期: 5/20/2004
Oleg Tkachenko
2004 年 4 月
适用于: 可扩展标记语言 (XML) 1.0 Microsoft .NET 框架
摘要:本文探讨了如何从多个文档构造单个 XML 文档的问题。它重点讨论了 XML Inclusions (XInclude),这是一种便于您用 XML 实现模块化的多用途机制。(15 页打印页)
下载 XInclude.NET-1.2.exe 示例代码。
500)this.width=500'>
本页内容
500)this.width=500'>
简介
500)this.width=500'>
为什么要使用 XInclude?
500)this.width=500'>
50,000 英尺以外的 XInclude
500)this.width=500'>
XInclude 语法
500)this.width=500'>
XInclude 处理模型
500)this.width=500'>
XPointer
500)this.width=500'>
XInclude 用法实践
500)this.width=500'>
小结
500)this.width=500'>
致谢
简介
模块化编程的思想要求您将任务细分成小的可管理单位。这种思想也适用于制作 XML 文档。通常,从几个较小的文档生成一个大型文档是有意义的。需要这种模块化方法的一些情况包括:将多个章节编撰成一部书,从单独维护的文档生成网页,或将标准页脚(例如,公司的免责声明)添加到文档中。
有很多方法可以解决如何从多个文档构造出单个 XML 文档的问题。本文重点讨论一个方法,该方法注定是便于用 XML 实现模块化的通用多用途机制:XML Inclusions (XInclude)。
500)this.width=500'>返回页首
为什么要使用 XInclude?
读者可能会问的第一个问题是:“为什么要使用 XInclude,而不是 XML external entities?”答案是,XML 外部实体有很多众所周知的局限和不便于使用的含义,这些因素极大地妨碍了 XML 外部实体成为多用途包含工具。具体来说:
•
XML 外部实体无法成为一个成熟的独立 XML 文档,因为它既不允许独立的 XML 声明,也不允许 Doctype 声明。这实际上意味着 XML 外部实体本身无法包括其他外部实体。
•
XML 外部实体必须是格式规范的 XML(第一眼看起来好象没有这么差,但想象一下怎样将示例 C# 代码包括到 XML 文档中)。
•
未能加载外部实体是重大错误 (fatal error);严格禁止任何恢复。
•
只能包括整个外部实体,无法只包括文档的一部分。
•
外部实体必须在 DTD 或内部子集中进行声明。这将打开有很多含义的潘多拉盒子,例如,这些含义可能是:要求文档元素必须在 Doctype 声明中命名,以及对读取方的验证可能需要在其他文档的 DTD 中定义文档的全部内容模型。
人们认识到将 XML 外部实体用作包含机制的缺点已经有一段时间了,实际上,这些缺点导致了在 1999 年由 Microsoft 和 IBM 将 XML Inclusion Proposal 提交到 W3C。该建议定义了一个多用途 XML 包含工具的处理模型和语法。
几年后,XML Inclusions(也称为 Xinclude)的 1.0 版本成为 Candidate Recommendation,这意味着 W3C 相信它已经被广泛审阅并且解决了它要解决的基本技术问题,但它还没有成为正式建议。
那么,XInclude 真的解决了上述问题吗?当然。让我们来看它是如何做到的。
500)this.width=500'>返回页首
50,000 英尺以外的 XInclude
XInclude 定义了一个便于在 XML 文档中实现模块化的多用途包含机制。包括过程被正式定义为将很多 XML 信息集 (XML Infoset) 合并到单个复合的 XML 信息集中。作者通过包含指令来指定要合并哪些文档并控制合并过程。包含指令的 XInclude 语法基于大家熟悉的、容易产生和处理的 XML 构造:元素、属性和 URI 引用。
XInclude 支持包含非 XML 文本文档,并允许作者控制恢复过程。例如,您可以提供要包含的默认内容或备用文档,如果无法加载远程资源,就将包括这些默认内容或备用文档。
XInclude 还支持部分 XML 包含,也就是说,您可以定义(通过提供 XPointer 指针)应当包括 XML 文档的哪一(些)部分。
下面的基本 XInclude“Hello World”示例可以更清楚地演示这个机制。假如您有一些网页定义,并且想让它们全都包括带有公司版权信息的模板页脚:
page.xml:<?xml version="1.0"?>
<webpage>
<body>Hello world!</body>
<xi:include href="templates/footer.xml" xmlns:xi="http://www.w3.org/2003/XInclude"/>
</webpage>
footer.xml:<?xml version="1.0"?>
<footer>? Contoso Corp, 2003</footer>
page.xml after XML Inclusion processing:<?xml version="1.0"?>
<webpage>
<body>Hello world!</body>
<footer xml:base="templates/footer.xml">? Contoso Corp, 2003</footer>
</webpage>
500)this.width=500'>
图 1“Hello World!”XInclude 示例。
下面是另一个介绍性示例,它演示了如何将外部非 XML 文本数据包含到 XML 文档中。假设您有一个存储在服务器上的 XML 文档,并且您想让它包含一个计数器,该计数器描述文档访问的次数:<?xml version="1.0"?>
<catalog xmlns:xi="http://www.w3.org/2003/XInclude">
<p>This document has been accessed
<xi:include href="http://www.contoso.com/Counter.aspx?pid=catalog" parse="text"/> times.</p>
</catalog>
这是 XML Inclusion 处理后的文档:<?xml version="1.0"?>
<catalog xmlns:xi="http://www.w3.org/2003/XInclude">
<p>This document has been accessed
45453 times.</p>
</catalog>
500)this.width=500'>返回页首
XInclude 语法
XInclude 语法非常简单,只是在 http://www.w3.org/2003/XInclude 命名空间中的两个元素,即 include 和 fallback。常用的命名空间前缀是“xi”(但可以根据喜好自由使用任何前缀)。对于那些习惯使用正式语法定义的人,XInclude 规范提供了 XInclude 的 XML 架构和 DTD。对于其他人,下面是它的摘要:
xi:include 元素
xi:include 元素充当包括指令。它定义了要包括哪些文档以及如何包括。它的属性是:
•
href — 对要包括的文档的 URI 引用。
•
parse — 它的值可以是“xml”或“text”,用于定义如何包括指定的文档(是作为 XML 还是作为纯文本)。默认值是“xml”。
•
xpointer — 这是一个 XPointer,用于标识要包括的 XML 文档部分。如果作为文本包括 (parse="text"),将忽略该属性。
•
encoding — 作为文本包括时,该属性提供所包括文档的编码提示信息。
•
注 请回忆一下,通常,没有人可以说出任意一个文本文件的编码是什么。幸运的是,XML 不受这个问题的影响(因为如何检测 XML 文档的编码有严格的规则),这就意味着如果是作为 XML (parse="xml") 完成包括的,就可以忽略 encoding 属性。
•
accept、accept-charset 和 accept-language — 这些属性可以用来帮助进行 HTTP content negotiation。当 XInclude 处理器通过 HTTP 协议取得资源时,它应当使用这些属性的值来设置 HTTP 请求中的 Accept、Accept-Charset 和 Accept-Language 头。如果对于相同的资源,单个 URI 可能基于 HTTP 头分析返回不同的表示形式(比如说,原始 XML 或 XHTML、ISO88591 或 UTF-8 编码、英语版本或希伯来文版本),那么该工具应该针对一种情况。
xi:include 元素可能只包含一个可选的 xi:fallback 元素,任何其他内容仅仅被忽略。
xi:fallback 元素
xi:fallback 元素提供了一个在丢失资源后恢复的机制。如果要包括的资源由于任何原因(连接问题、安全限制、资源不存在、URI 架构未知或者像 mailto: 一样不可获取,等等)而不可用,那么将包括 xi:fallback 元素的内容。下面的示例显示了如何使用 xi:fallback 元素: <page xmlns:xi="http://www.w3.org/2003/XInclude">
<header>New This Week from MSDN</header>
<xi:include href="http://msdn.microsoft.com/rss.xml">
<xi:fallback>Sorry, MSDN news are unavailable.<xi:fallback>
</xi:include>
</page>
如果资源丢失并且 xi:include 元素为空,则不会包括任何内容。xi:fallback 元素没有属性,它必须是 xi:include 元素的直接子集,并且它的内容是不受限制的。由于对 xi:fallback 元素的内容没有限制,因此,它就可以包含另一个 xi:include 指令,从而提供要包括的可选恢复资源:<page xmlns:xi="http://www.w3.org/2003/XInclude">
<header>New This Week from MSDN</header>
<xi:include href="http://msdn.microsoft.com/rss.xml">
<xi:fallback>
<xi:include href="http://msdn.microsoft.com/xml/rss.xml">
<xi:fallback>Sorry, MSDN news are unavailable.<xi:fallback>
</xi:include>
<xi:fallback>
</xi:include>
</page>
保存基本 URI
留心的读者可能已经注意到出现在结果文档中的 xml:base 属性。这是一个重要的功能,当文档被包括到另一个文档(可能在其他位置)中时,它可以防止在被包括的文档中的相对 URI 引用被破坏。请参考下例。
位于 C:\Contoso\Inventory 目录中的 parts.xml 文档使用相对 URI 引用来引用相同目录中的 XML 架构 parts.xsd:<parts xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="parts.xsd">
<part SKU="10023" quantity="100"/>
</parts>
位于 C:\Contoso\Reports 目录中的 report.xml 文档包括 parts.xml:<report>
<inventory>
<xi:include href="C:\Contoso\Inventory\parts.xml"
xmlns:xi="http://www.w3.org/2003/XInclude"/>
</inventory>
</report>
经过 XML Inclusion 处理之后,report.xml 文档如下所示:<report>
<inventory>
<parts xmlns:xsi="http://www.w3.org/2003/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="parts.xsd"
xml:base="../Inventory/parts.xml">
<part SKU="10023" quantity="100" />
</parts>
</inventory>
</report>
注意 xml:base 属性是如何保存被包括文档的基本 URI 的,该属性使 xsi:noNamespaceSchemaLocation 属性中的相对 URI 引用指向位于 C:\Contoso\Inventory 目录中的相同架构文件。
500)this.width=500'>返回页首
XInclude 处理模型
从技术上讲,XInclude 将包含定义为特殊类型的 XML 信息集转换。源信息集转换为结果信息集后,在结果信息集中每个 xi:include 元素被替换为它引用的信息集。该过程也可以被看作是信息集的合并。
XML Inclusion 是一个递归过程,因此,还会处理被包含文档中的每个 xi:include 元素。当然,为了保证安全,循环包含将会被检测,并将其当作重大错误。什么是重大错误?XInclude 定义了两种类型的错误,这两类错误都可能在包含过程中发生:“重大错误”,可以想象它是指出现了使正常处理过程无法继续的因素;和“资源错误”,这是指获取资源的尝试失败。重大错误是致命的,这就意味着处理过程必须停止,而资源错误则可后进行处理。
现在来看看如何处理 xi:include 元素。首先,它依赖于 parse 属性值。当 parse="xml" 时(顺便说一句,这是默认值),获取引用的文档,并将该文档解析为 XML,然后替换源信息集以及其后代中的 xi:include 元素。可以设想,试图包含格式不规范的 XML 文档将导致重大错误,因为格式的规范性是 XML 的“圣杯”(译注:Holy Grail — 圣杯/圣盘,据中世纪传说为基督在最后的晚餐上用过的那个杯或盘子,后来成为许多骑士追求的目标,此处是指格式的规范性是编写 XML 文档时追求的目标)。
如果 parse="text",将获取引用的文档,并将它视为纯文本,然后以同样方式替换 xi:include。这是非常有用的功能,例如,它允许将源代码或 XML 文档作为文本进行包含。如下示例显示了将 XML 文档作为文本包含在另一个文档中:<doc xmlns:xi="http://www.w3.org/2003/XInclude">
For instance, consider the following SOAP message request to the Contoso Delivery Web Service:
<xi:include href="contoso-soap.xml" parse="text"/>
</doc>
执行 XML Inclusion 之后,结果文档如下所示:<doc xmlns:xi="http://www.w3.org/2003/XInclude">
For instance, consider the following SOAP message request to the Contoso Web Service:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<Delivery xmlns="http://www.contoso.com">
<address>
<Street>One Microsoft Way</Street>
<City>Redmond</City>
<Zip>98052</Zip>
</address>
</Delivery>
</soap:Body>
</soap:Envelope>
</doc>
注意左尖括号字符被转义,因为整个 contoso-soap.xml 文档(尽管它是 XML)是作为单个文本节点被包含的。
在另一个文本包含可能有用的有趣事例中,您希望在 XSL 转换期间包含某个外部文本文档。虽然 XSLT 1.0 有 document() 函数,但该函数只允许您打开外部 XML 文档,而不能打开纯文本文档。例如,要将 CSS 文件包含到生成的 HTML 文档中,只要一个 xi:include 指令就足够了:<xsl:template match="page">
<html>
<head>
<style type="text/css">
<xi:include href="main.css" parse="text"/>
</style>
...
由于显而易见的原因,您仍然无法用该方式包含二进制资源。试图包含 XML 1.0 建议所不允许的字符将导致重大错误。
500)this.width=500'>返回页首
XPointer
到此为止,都很顺利。上面提供的示例说明了如何包含整个文档,但如果只需包含文档的一部分(比如说,包括某个书籍目录中特定作者的所有书籍),又该怎么办呢?请输入 XPointer。XInclude facilitates partial inclusion using XPointer pointers in xpointer attribute:
<para>
My favorite books are:
<xi:include href="books.xml" xpointer="xpointer(//book[@author='Stephen King'])"/>
</para>
上面的指令包含了所有 book 元素,它们的 author 属性值是来自 books.xml 文档的“Stephen King”。圆括号中的表达式您应当非常熟悉。它是 XPath 吗?不完全对,但非常接近。它是特殊类型的 XPointer,或更准确地说,是指向特殊 XPointer 架构 xpointer() 的指针,而 xpointer() 是 XPath 的扩展。现在让我们循序渐进地看一看 XPointer 的原理。
XPointer 代表“XML 指针语言”,它是用于进行 XML 寻址的可扩展的系统。XPointer 的基础是 XPointer 框架,后者定义了段落标识符的语义和基本语法。XPointer 框架定义了两种类型的指针:快捷 (shorthand) 指针和基于架构 (scheme-based) 指针。
快捷指针(以前称为 barename)事实上是对HTML 中段落标识符的大致模拟,后者指向命名定位点。而 XPointer 快捷指针最多只能按元素 ID 标识 XML 文档中的一个元素。ID 可以由 DTD、XML 架构或以应用程序特有的方式确定。<xi:include href="books.xml" xpointer="bk101"/>
xpointer 属性中的 bk101 值就是一个快捷 XPointer 指针,它标识了 books.xml 文档中的某个元素,该元素的 ID 是“bk101”。
基于架构的指针是更复杂的指针类型,它由指针部分的序列组成,并可选择用空格分开。每个指针部分有一个架构名称和一些放在圆括号中的、架构特有的数据,例如 element(bk101) 或 xpointer(//book):<xi:include href="books.xml" xpointer="element(bk101)xpointer(//*[@title='Dreamcatcher'])"/>
在以前的包含指令中,xpointer 属性值表示基于架构的 XPointer 指针,该指针标识了在 books.xml 文档(其 ID 是 bk101)中的元素,或者如果无法找到这样的元素,则它标识其 title 属性值是 Dreamcatcher 的元素。
500)this.width=500'>
图 2基于架构的 XPointer 指针结构
指针部分是按从左到右的顺序计算的,直到某个部分识别出某个子资源。无法识别或不被支持的部分将被忽略。但要注意,如果整个指针中没有任何指针部分能够识别子资源,则会发生错误。快捷指针同样如此。
如您所见,基于架构的指针提供了一种使段落标识更可靠的方式,因而允许您指定几个指针部分,其中每个部分可以按不同方式指向希望的子资源。如果指针部分未能识别子资源,则继续计算下一个指针部分,实际上提供某种替换的寻址行为。
XPointer 架构
W3C 定义了三种类型的 XPointer 架构,即 element()、xmlns() 和 xpointer()。另外,Simon St.Laurent 建议 xpath1() scheme,该架构使用规则的 XPath 1.0 语法,就像在 xpath1(//book) 中一样。
此 element() 方法便于按 ID(就像快捷指针一样)和按同辈元素之间的位置编号进行基本的 XML 元素寻址。例如,element(/1/3) 指针部分标识了根元素的第三个子元素,而 element(bk101/2) 则标识了 ID 为 bk101 的元素的第二个子元素。
xmlns() 架构表示辅助指针部分,它永远不标识自己的任何子资源,但允许定义绑定了其他指针部分的上下文的命名空间(这样,就可以根据需要将任意多个指针部分组合在一起)。例如,下面的 XPointer 指针标识了在属于“http://www.contoso.com”命名空间的文档中的所有 book 元素:xmlns(co=http://www.contoso.com)xpointer(//co:book)
xpointer() 架构的功能最强大。它为对 XML 文档的各部分进行寻址提供了高级别的功能。它基于 XPath 1.0,并将 XPath 扩展为允许对字符串、点和范围进行寻址。请注意,xpointer() 架构仍然在发展,并且很可能有进一步的变化。
现在回到对 XInclude 的讨论。XInclude 规范要求任何符合规范的 XInclude 处理器都必须支持 XPointer 框架和 element() 架构。这实际上意味着您只能安全地使用文档中的快捷指针和基于 element() 架构的指针,但既然 Xinclude 还在发展之中,所以最好经常查阅 XInclude 处理器的文档。
我们已经讨论完理论部分。现在谈谈实践中如何编程。
500)this.width=500'>返回页首
XInclude 用法实践
我们首先需要支持 Xinclude 的环境。不要指望您喜欢的 XML 语法分析程序自动支持 XInclude。例如,很遗憾 MSXML 和 System.xml 都不支持 Xinclude。W3C 在 XInclude Implementations Report 中列出了可用的 XInclude 实现。其中一些实际上仅用于实验,但有几个具有生产水准。
我最喜欢的 XInclude 实现 XInclude.NET,这可能因为我是此项目的首席开发人员。
用于 .NET 的 XInclude — XInclude.NET
XInclude.NET 项目受到 Chris Lovett 的 XInclude, Anyone? 一文启发,发现这篇文章时,我正在解决类似的问题:如何利用由不同团队分别编写的文档编撰出网页。通过方便地利用 .NET 框架的强大功能,可以在 System.Xml API 之上建立健壮、高性能的 XInclude 处理器。XInclude.NET 库的 1.2 版本最近已经发布,现在用户可以判断是否已实现该目标。
XInclude.NET 项目是 2003 年 11 月 10 日发布的 XInclude 1.0 Last Call Working Draft (编写本文时的最新版本)的实现,是用 .NET 框架的 C# 编写的。此外,它支持 XPointer 框架、element()、xmlns()、xpath1() 和 xpointer()(仅 XPath 子集)架构。本文所附的代码示例包含 XInclude.NET 1.2 版本,该版本提供了预编译的 XInclude.dll 程序集、API 文档、示例和 XInclude 实现的源代码。
XInclude.NET 中的关键类是 XIncludingReader,可以在 GotDotNet.XInclude 命名空间中找到它。主要设计目标是为 XML 处理建立可插接的流管道。为了实现这个目标,XIncludingReader 实现了一个 XmlReader,该 XmlReader 可以围绕在另一个 XmlReader 的周围。该体系结构允许在不作任何重大修改的情况下将 XInclude 处理层很容易地插入到各种应用程序中。例如,当 XML 正在加载到 XmlDocument 中时,如果要启用对该 XML 的 XInclude 处理,只需用 XIncludingReader 将 wrapXmlTextReader 包装起来:using System.Xml;
using GotDotNet.XInclude;
public class Class1 {
public static void Main(string[] args) {
XmlTextReader r = new XmlTextReader("document.xml");
XIncludingReader xir = new XIncludingReader(r);
XmlDocument doc = new XmlDocument();
doc.Load(xir);
//...
}
}
在执行 XSL 转换之前的 XML Inclusion 是同样简单的:using System.Xml;
using System.Xml.XPath;
using System.Xml.Xsl;
using System.IO;
using GotDotNet.XInclude;
public class Class1 {
public static void Main(string[] args) {
XIncludingReader xir = new XIncludingReader("document.xml");
XPathDocument doc = new XPathDocument(xir);
XslTransform xslt = new XslTransform();
xslt.Load("stylesheet.xslt");
StreamWriter sw = new StreamWriter("result.html");
xslt.Transform(doc, null, sw);
sw.Close();
}
}
前面显示的 CSS 包含的示例假定 XSLT 样式表由 XInclude 处理器处理;以下代码显示了如何完成该操作:public class Class1 {
public static void Main(string[] args) {
XPathDocument doc = new XPathDocument("document.xml");
XslTransform xslt = new XslTransform();
XIncludingReader xir = new XIncludingReader("stylesheet.xslt");
xslt.Load(xir);
StreamWriter sw = new StreamWriter("result.html");
xslt.Transform(doc, null, sw);
sw.Close();
}
}
XML Inclusion 过程与 XML 语法分析、验证或转换没有关系。这实际上意味着由您决定在什么时候允许 XML Inclusion 发生:是在语法分析之后,但在验证之前;还是在验证之后,但在转换之前,甚至在转换之后。
注 在执行 XML Inclusion 期间保存基本 URI 意味着在结果文档中会出现 xml:base 属性。这实际上意味着在“预验证包含”方案中 XML 架构作者应当期望 xml:base 属性出现在所包括的元素的最上层。实际上,xml:base 属性是核心标准 XML 属性,所以在这里有必要允许在架构中对每个元素包含 xml:base 属性。
XIncludingReader 如何工作
注 必须熟悉 XmlReader 体系结构。否则可以跳过本节。
XIncludingReader 实现基于 XmlReaders 链 (chaining) 技术,.NET Framework Developer's Guide 中的 Customized XML Reader Creation 一节对此进行了描述。该技术与旧式 SAX 筛选很相似,它允许通过委托调用将 XmlReaders 进行链化,从而有效地提供高性能的方法来筛选或修改 XML(当 XML 正在被读取时)。
500)this.width=500'>
图 3 一条 XmlReaders 链
XIncludingReader 总是工作在另一个读取器(SAX 术语叫“父”读取器,它为 XIncludingReader 提供输入 XML 流)之上。当 XIncludingReader 的输入与 XmlReader 不兼容时(如在 System.IO.Stream 或 System.IO.TextReader 中),将实例化一个临时 XmlTextReader 对象来充当父读取器。所得到的 XML(在完成 XML Inclusion 的位置)可以被 XIncludingReader 自己的客户端应用程序读取;记住,它只是 XmlReader。
大多数时候,XIncludingReader 不做任何事情;它只是向父读取器委派方法调用,并透明地公开父读取器的属性(例如,名称或值)来作为它自己的属性。虽然这样,但它总是监视父读取器所报告的 XML 元素的名称。一旦将父读取器放在 xi:include 元素上,XIncludingReader 就会被激活并开始执行包含过程。
父读取器并不会将 xi:include 元素公开给客户端应用程序,而是被压入堆栈,并实例化新的临时 XmlReader 以读取 xi:include 指令所引用的文档。该临时读取器的实际类型取决于是否存在 xpointer 属性(如果是这样,它会成为一个专用的 XPointerReader,它将实现 XPointer 并只读取指针节点所标识的内容),或者取决于包含操作是否是在文本模式下完成的(如果是这样,它会成为一个专用的 TextIncludingReader,它将把整个文档作为单个文本节点进行读取)。否则,它的行为只像一个 XmlTextReader。
不管怎样,父读取器都将被压入堆栈,而这个新的读取器会成为父读取器。普通读取会继续进行下去,直到从父读取器读取不到输入。之后,包括过程执行完毕,并且前一个父读取器从堆栈中弹出。
虽然这听起来很简单,但请记住这只是冰山一角。隐藏的部分超出了本文的范围,这些部分包括实现后备处理和极其重要地公开 XmlReader API 中的综合 xml:base 属性(Martin Gudgin 在他的网络日记中对此进行了详细介绍)。如果想要了解更多内容,只需深入阅读源代码。另外,请在该项目的 message board 上大胆地询问任何与 XInclude.NET 有关的问题,并将错误提交到 bug tracker。
这样的仅向前、非缓存的流实现会占用非常少的内存,并且几乎不会对性能造成任何不利影响。在大多数时间里,XIncludingReader 所做的全部操作只是比较元素的名称、监视 xi:include 元素。在考虑到 XmlNameTable 的情况下,假设比较已经完成,这将是非常廉价的操作(因此,在 99% 的情况下这只是对两个对象指针进行的比较)。
遗憾的是,对 XPointer 指针的处理并不是低成本的。事实上,它需要将整个包含的文档加载到内存中,只是为了按 ID、XPath 选择路径或按 xpointer() 指针选择所需的部分。有趣的是,对 XPointer 指针的计算是通过将 XPointer 语法转换成 XPath 表达式在内部实现的,如下所示:
1.
快捷指针被转换成 id() function 调用:从 bk101 到 id('bk101')。
2.
基于 element() 架构的指针被转换成 XPath 选择路径,其中包含 id() 函数调用和/或位置谓词:从 element(bk101)/3 到 id('bk101')/*[3]。
3.
基于 xpointer() 架构的指针被直接用作 XPath 表达式。这就是为什么 XInclude.NET 不支持 XPath 的 xpointer() 超集的原因。
未来的 XInclude.NET 版本可能提供更完整和更有效的 XPointer 实现。
500)this.width=500'>返回页首
小结
XInclude 是正在发展的 W3C 标准,旨在便于实现 XML 中的模块化。它定义了对 XML 文档进行多用途包含或合并时所需的处理模型和语法。它不依赖于 XML 语法分析和验证,并且它的语法基于 XML 元素、属性和 URI 引用。
尽管 XInclude 还不是 W3C 推荐标准,但它的实现数量以及它在 XML 社区受到的欢迎正在不断增长。在本文中,我们已经介绍了 XInclude 和 Xpointer。我们还会讨论针对 .NET 框架的具体的 XInclude 实现。
500)this.width=500'>返回页首
致谢
我十分感谢 Dare Obasanjo 在我准备本文时提供的全部帮助。
转到原英文页面
|
|
|

.: 公告
This blog focuses on:
Semantic Web && Java Technology |
|
« | October 2025 | » | 日 | 一 | 二 | 三 | 四 | 五 | 六 | | | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | | |
|
.: 我的分类(专题)
|

.: 最新日志
.: 最新回复
|

blog名称:SW Portal 日志总数:171 评论数量:219 留言数量:8 访问次数:1050869 建立时间:2004年10月30日 |
|

.: 留言板
|

.: 链接
|

|