UML软件工程组织

了解 XML
Dare Obasanjo
Microsoft Corporation 
2003年7月    
摘要:了解可扩展标记语言 (XML) 如何帮助我们实现通用的数据访问。XML 是一种基于 Unicode 的纯文本元语言,即一种用于定义标记语言的语言。它不依赖于任何编程语言、操作系统或软件供应商。XML 可以提供对各种数据处理、构建、转换和查询技术的访问。(本文包含一些指向英文站点的链接。)

简介

最初设想的可扩展标记语言 (XML) 用于为 Web 定义新文档的格式。XML 由标准通用标记语言 (SGML) 衍生而来,可以认为它是一种元语言,即一种定义标记语言的语言。SGML 和 XML 都是基于文本的格式,提供了一种使用标记(文字由‘<’和‘>’括起)描述文档结构的机制。Web 开发人员可能会注意到,XML 与 HTML 有一些相似,这是因为这二者都是由 SGML 衍生而来的。

随着 XML 的应用日益普及,现在人们已普遍认同,XML 不仅有助于为 Web 描述新文档的格式,而且也适用于描述结构化的数据。所谓结构化的数据包括那些电子表格、程序配置文件和网络协议中通常所包含的信息。

XML 要优于早期的数据格式,因为 XML 可以很轻松地表示表格式的数据(如数据库中的关系数据或电子表格)和半结构化的数据(如 Web 页面或业务文档)。早已存在且应用广泛的一些格式(如逗号分隔值 [CSV] 文件)可以有效地处理表格式数据,却不能很好地处理半结构化数据,而 RTF 等则只能专门用于半结构化的文本文档。因此,XML 作为信息交换的通用语言被广泛接受。

无处不在的 XML

除了可以表示结构化和半结构化的数据之外,XML 还有许多其他特性,使其成为一种被广泛采用的数据表示格式。XML 是可扩展的,与平台无关的,并且由于其完全采用 Unicode 而支持国际化。XML 是基于文本的格式,因此,用户可以根据需要使用标准的文本编辑工具读取和编辑 XML 文档。

XML 的可扩展性表现在多个方面。首先,与 HTML 不同,XML 没有固定的词汇表。相反,用户可以使用 XML 定义特定的应用程序或行业专用的词汇表。其次,与使用其他格式的应用程序相比,处理或使用 XML 格式的应用程序对 XML 结构的更改更具“抵抗力”,只要这些更改是附加的。例如,如果某个应用程序主要处理具有 customer-id 属性的 <Customer> 元素,如果再向 <Customer> 元素添加一个 last-purchase-date 属性,该应用程序通常也不会被破坏。这样的适应性在其他的数据格式中很少见,这也成为使用 XML 的一个显著优势。

XML 不依赖于任何编程语言、操作系统或软件供应商。事实上,使用各种编程语言都可以很容易地生成或使用 XML。而平台独立性使得 XML 有助于在不同编程平台和操作系统之间实现互操作。

很多人已经意识到将数据发布为 XML 有很多优势,由此也推动了 XML 数据源的大量应用。人们正在或者已经将业务文档、数据库和业务间的通讯等信息源转换为使用 XML 作为表示格式。Microsoft 的产品,如 Microsoft Office®、Microsoft SQL Server™ 和 Microsoft .NET Framework,都能使最终用户和开发人员将文档、网络信息和其他数据生成为 XML 或作为 XML 使用。

XML 1.0 语法

如前所述,W3C XML 1.0 推荐描述了一种基于文本的格式,使用类似于 HTML 的语法来描述结构化和半结构化的数据。

XML 和 HTML 的对比

HTML 和 XML 文档都由元素组成,每个元素都包含一个“起始标记”(例如 <order>)、一个“结束标记”(例如 </order>),以及两个标记之间的信息(指元素的内容)。元素可以使用属性进行注解,属性包含了关于元素及其内容的元数据。

但是,HTML 与 XML 之间存在一个显著的差别,即 XML 区分大小写,而 HTML 不区分大小写。也就是说,在 XML 中,起始标记 <Table><table> 是不同的,而在 HTML 中则是相同的。HTML 与 XML 之间的另一个差别是,XML 引入了“良好结构”的概念。XML 的“良好结构”规则通过强制规定一些规则来消除在处理 HTML 等标记语言时存在的一些固有的模糊性,如它强制规定了所有属性都必须用括号括起,所有元素都必须具有一对起始标记和结束标记,或者明确指出其为空元素。有关良好结构的简短说明,请参阅“XML FAQ”的 D.2 部分。

HTML 与 XML 之间最显著的区别在于,HTML 已预先定义了元素和属性,元素和属性的行为已完全指定,而 XML 则不是这样。相反,文档作者可以创建自己的特定于其应用程序或业务需求的 XML 词汇表。目前已有的 XML 词汇表适用于许多行业和应用程序,从财务信息报告 (XBRL)、金融服务 (FpML) 到 Web 文档 (XHTML)、网络协议 (SOAP)。由于不必关注那些用来指定如何呈现或显示 XML 文档的预定义元素和属性,因此文档作者在创建文档时就可以将重点放在与其特定问题领域相关的语义信息上。XML 词汇表带来了内容与形式的分离,使得信息和内容可以得到更大规模的重复利用。

XML 文档剖析

以下示例是一个表示音像商店客户订单的 XML 文档。请注意,此文档既表示了严谨的结构化数据(用来描述光盘信息),也表示了半结构化数据(用来说明有关特定顾客的特殊说明和注释),而其表示方式非常简单。

<?xml version="1.0" encoding="iso-8859-1" ?>
<?xml-stylesheet href="orders.xsl"?>

<order id="ord123456">
  <customer id="cust0921">
    <first-name>Dare</first-name>
    <last-name>Obasanjo</last-name>
    <address>
      <street>One Microsoft Way</street>
      <city>Redmond</city>
      <state>WA</state>
      <zip>98052</zip>
    </address>
  </customer>
  <items>
    <compact-disc>
      <price>16.95</price>
      <artist>Nelly</artist>
      <title>Nellyville</title>
    </compact-disc>
    <compact-disc>
      <price>17.55</price>
       <artist>Baby D</artist>
       <title>Lil Chopper Toy</title>
    </compact-disc>
  </items>

  <!--  要多走几英里找到顾客 -->
  <special-instructions xmlns:html="http://www.w3.org/1999/xhtml/">
    <html:p>If customer is not available at the address then attempt 
      leave package at one of the following locations listed in order of 
      which should be attempted first 
    <html:ol>
      <html:li>Next Door</html:li>
      <html:li>Front Desk</html:li>
      <html:li>On Doorstep</html:li>
    </html:ol>
    <html:b>Note</html:b> Remember to leave a note detailing where 
      to pick up the package.
    </html:p>
  </special-instructions>
</order>

文档的开头是可选的 XML 声明,用以指定所使用的 XML 版本,然后是文档所使用的字符编码。接下来是 XML 样式表处理指令,用来绑定样式表。样式表中包含的 XML 文档的格式化指令可以用更生动的方式在用户应用程序(例如 Web 浏览器)中呈现 XML 文档。处理指令通常用来在 XML 文档中嵌入特定于应用程序的信息。例如,处理以上文档的大多数应用程序都会忽略 XML 样式表处理指令,而用于显示 XML 文档的应用程序(例如 Web 浏览器)则会使用处理指令中的信息,以确定将包含了用于显示文档的特殊指令的样式表定位在哪里。

Unicode + 尖括号 = 互操作

XML 1.0 语法是基于文本的,而且可以很容易地进行分析,这使得 XML 在需要跨平台进行交互操作时,成为首选的数据交换格式。在多种常用的操作系统中都可以使用 XML 分析器,因此,不同平台上完全不同的部件在需要共享信息时,可以很容易地进行标准化,采用 XML 作为交换格式。

以 Unicode 为基础的 XML 也适用于在全球网络中共享信息,例如在 Web 上。

信息集 (Infoset) 和 XML 系列技术

尽管使用 XML 作为数据表示格式可以带来一个极大的优势:通过使用基于文本的 XML 语法获得平台互操作性和可扩展性,但这只是 XML 为应用程序开发人员带来的益处之一。使用 XML 的另一个主要好处在于,用户可以访问各种数据处理、构建、转换和查询技术。

XML 信息集

W3C XML Information Set 推荐描述了 XML 文档的抽象表现形式。XML 信息集主要用作各种 XML 技术使用的定义集,以正式描述需要技术处理的 XML 文档部分。有几种 W3C XML 技术是按照 XML 信息集进行描述的,包括 SOAP 1.2、XML 架构和 XQuery。

XML 信息集是 XML 文档的树状层次表示。一个 XML 文档的信息集包含许多信息项,这些信息项是 XML 文档组件的抽象表示,其中包括表示文档、文档的元素、属性、处理指令、注释、字符、表示法、命名空间、未分析的实体、未扩展的实体引用和文档类型声明的信息项。XML 信息集是被正式推荐的机制,通过它来定义 XML 文档中应被重视的重要信息。例如,信息集不区分空元素的两种形式。因此根据 XML 信息集,以下两种表示方法

  <test></test>
  <test/>

是相同的。同样,属性所使用的引号类型也不重要,因此根据 XML 信息集,元素

  <test attr='value'/>
  <test attr="value"/>

是相同的。XML 信息集认为不重要的 XML 1.0 语法内容列表在 W3C XML Information Set 推荐的附录 D 中提供。

XML Information Set 推荐介绍了“综合信息集 (Synthetic Infosets)”的概念。所谓综合信息集是指除使用分析文本形式的 XML 文档之外还用其他方法创建的信息集。综合信息集为使用 XML 技术处理非 XML 数据奠定了基础,当然前提是此类数据可以映射到 XML 信息集。处理综合信息集的一个示例是 ObjectXPathNavigator,它允许用户在 .NET Framework 中使用 Xpath 查询对象,或者使用 XSLT 转换对象。

架构语言

XML 架构语言用于描述 XML 文档的结构和内容。例如,可以使用架构指定文档中包含一个或多个 compact-disc 元素,而每个 compact-disc 元素都包含子元素 pricetitleartist。在交换文档的过程中,XML 架构可以描述 XML 生成程序与使用程序之间的约定,因为它描述了这二者之间的有效 XML 消息的组成。虽然存在大量用于 XML 的架构语言,从 DTD 到 XDR,但目前最权威的是 W3C XML 架构定义语言,通常简称为 XSD。

XSD 在 XML 架构语言中是独一无二的,因为它最先尝试扩展 XML 架构的作用,使之不再局限于仅用来描述两个实体交换文档时的约定。XSD 引入了“后架构验证信息集 (Post Schema Validation Infoset,PSVI)”的概念。一个完整的 XSD 处理器接受 XML 信息集作为输入,并在验证时将其转换为后架构验证信息集 (PSVI)。PSVI 是初始的输入 XML 信息集,带有添加的新信息项和添加到现有信息项中的新属性。W3C XML Schema 推荐列出了后架构验证的信息集的组成要素。

类型注释是 PSVI 组成要素中很重要的一类。元素和属性需进行严格的类型定义,并具有与之相关的数据类型信息。经过严格类型定义的 XML 有很多用途,可以使用 .NET Framework 的 XmlSerializer 等技术将其映射到对象,可以使用 SQLXML 和 .NET Framework 的 DataSet 技术将其映射到关系表格,或者使用利用了严格类型机制的 XML 查询语言,如 XPath 2.0 和 XQuery 对其进行处理。

以下示例是一个架构片段,描述了 XML 文档剖析 一节中示例文档的 items 元素。

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="items">
  <xs:complexType>
    <xs:sequence>
      <xs:element ref="compact-disc" minOccurs="0" maxOccurs="unbounded" />
    </xs:sequence>
  </xs:complexType>
</xs:element>

<xs:element name="compact-disc">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="price" type="xs:decimal" />
      <xs:element name="artist" type="xs:string" />
      <xs:element name="title" type="xs:string" />
    </xs:sequence>
  </xs:complexType>
</xs:element>

</xs:schema>

基于树模型的 API

树模型 API 将 XML 文档呈现为由节点组成的树,这个树通常可以立即加载到内存中。最常用的 XML 树模型 API 是 W3C 文档对象模型 (DOM)。DOM 支持以编程方式读取、处理和修改 XML 文档。

以下示例使用 .NET Framework 中的 XmlDocument 类获取 items 元素中第一个 compact-disc 的艺术家姓名和标题。

using System; 
using System.Xml; 

public class Test{

  public static void Main(string[] args){

    XmlDocument doc = new XmlDocument(); 
    doc.Load("test.xml"); 

    XmlElement firstCD = (XmlElement) doc.DocumentElement.FirstChild;
XmlElement artist  = 
(XmlElement) firstCD.GetElementsByTagName("artist")[0];
    XmlElement title   =
(XmlElement) firstCD.GetElementsByTagName("title")[0]

    Console.WriteLine("Artist={0}, Title={1}", artist.InnerText, title.InnerText);
  }
}

基于游标的 API

XML 游标 API 就像在 XML 文档中移动的镜头,对准被定向的文档的各个方面。.NET Framework 中的 XPathNavigator 类就是一个 XML 游标 API。XML 游标 API 与树模型 API 相比,具有不必将整个文档加载到内存中的优势,这样便于对 XML 生成程序中按需生成文档的部分进行优化。

以下示例使用 .NET Framework 中的 XPathNavigator 类获取 items 元素中第一个 compact-disc 的艺术家姓名和标题。

using System; 
using System.Xml; 
using System.Xml.XPath; 

public class Test{

  public static void Main(string[] args){

    XmlDocument doc = new XmlDocument(); 
    doc.Load("test.xml"); 

    XPathNavigator nav = doc.CreateNavigator(); 

    nav.MoveToFirstChild(); //从根节点移至文档元素 (items)
    nav.MoveToFirstChild(); //从 items 元素移至第一个 compact-disc 元素
    
    //从 compact-disc 元素移至 artist 元素
    nav.MoveToFirstChild();
    nav.MoveToNext(); 
    string artist = nav.Value; 

    //从 artist 元素移至 title 元素
    nav.MoveToNext(); 
    string title = nav.Value; 

    Console.WriteLine("Artist={0}, Title={1}", artist, title);
  }
}

流式 API

使用处理 XML 的流式 API 时,用户只需在内存中存储要处理的当前节点的上下文,即可处理 XML 文档。此类 API 可以处理大型的 XML 文件,而不会占用庞大的内容空间。用于 XML 处理的流式 API 主要有两种类型:基于推进的 XML 分析器和基于拉出的 XML 分析器。

基于推进的分析器(如 SAX)的工作方式是在 XML 数据流中移动,并在遇到 XML 节点时将事件“推进”到已注册的事件处理程序(回调方法)。基于拉出的分析器(如 .NET Framework 中的 XmlReader 类)则在 XML 数据流中用作只向前的游标。

以下示例使用 .NET Framework 中的 XmlReader 类获取 items 元素中第一个 compact-disc 的艺术家姓名和标题。

using System; 
using System.Xml; 

public class Test{

  public static void Main(string[] args){

    string artist = null, title = null; 
    XmlTextReader reader = new XmlTextReader("test.xml"); 

    reader.MoveToContent(); //move from root node to document element (items)

    /* 保持读取,直至获得第一个 <artist> 元素 */
    while(reader.Read()){

      if((reader.NodeType == XmlNodeType.Element) && reader.Name.Equals("artist")){

        artist = reader.ReadElementString();
        title  = reader.ReadElementString(); 
        break; 
      }
    }
    Console.WriteLine("Artist={0}, Title={1}", artist, title);
  }
}

XML 查询

在有些情况下,使用 API 从 XML 文档中提取信息可能会过于烦琐,这或者是由于查找数据的条件过于简略,或者是由于 API 未能呈现用于特定查询的 XML 文档的特定内容。XML 查询语言(如 XPath 1.0 和即将发布的 XQuery)都提供了从 XML 信息集中提取信息的丰富机制。

以下示例显示了如何使用 XPath 获取 items 元素中第一个 compact-disc 的艺术家姓名和标题。

using System; 
using System.Xml.XPath; 

public class Test{

  public static void Main(string[] args){
    
    XPathDocument doc   = new XPathDocument("test.xml"); 
    XPathNavigator nav  = doc.CreateNavigator(); 

    XPathNodeIterator iterator = nav.Select("/items/compact-disc[1]
/artist | /items/compact-disc[1]/title");

    iterator.MoveNext();
    Console.WriteLine("Artist={0}", iterator.Current);

    iterator.MoveNext();
    Console.WriteLine("Title={0}", iterator.Current);

  }
}

XML 转换

用户经常需要将 XML 文档从一个词汇表转换到另一个词汇表。这样做有时是为了以便于打印的格式或在 Web 浏览器中呈现文档,有时是可能需要将从外部实体接收的文档转换为较为熟悉的格式。

XSLT 是一种优秀的 XML 转换语言。XSLT 中阐述的转换说明了将源树转换为结果树的规则。转换通过关联模式和模板来完成。一个模式是一个 XPath 表达式,可以将其视为与 XML 源树的部分相匹配的正则表达式,与字符串的匹配部分相对。模式与源树中的元素进行匹配。成功匹配后,模板成为创建结果树部分的例示。在构建结果树时,可以对源树中的元素进行筛选和重新排序,还可以添加任意结构。

以下 XSLT 样式表将 items 元素转换为包含光盘信息表的 XHTML Web 页。

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" 
xmlns="http://www.w3.org/1999/xhtml">

<xsl:output method="xml" indent="yes"
    doctype-system="
http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" 
    doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" />


    <xsl:template match="/">

    <html lang="en" xml:lang="en">
     <head>
      <title>Order Information - ord123456</title>
     </head>
     <body>
       <table border="1">
        <tr><th>Artist</th><th>Title</th><th>Price</th></tr>

        <xsl:for-each select="items/compact-disc">
        <tr>
        <td><xsl:value-of xmlns="" select="artist" /></td>
        <td><xsl:value-of xmlns="" select="title" /></td>
        <td><xsl:value-of xmlns="" select="price" /></td>
        </tr>
        </xsl:for-each>

       </table>
     </body>     
    </html>
     
   </xsl:template>

</xsl:stylesheet>

XHTML 文档由如下所示的样式表生成:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>Order Information - ord123456</title>
  </head>
  <body>
    <table border="1">
      <tr>
        <th>Artist</th>
        <th>Title</th>
        <th>Price</th>
      </tr>
      <tr>
        <td>Nelly</td>
        <td>Nellyville</td>
        <td>16.95</td>
      </tr>
      <tr>
        <td>Baby D</td>
        <td>Lil Chopper Toy</td>
        <td>17.55</td>
      </tr>
    </table>
  </body>
</html>

它在 Web 浏览器中如下所示。

Artist Title Price
Nelly Nellyville 16.95
Baby D Lil Chopper Toy 17.55

小结

XML 不仅是一种描述文档的文本格式,还是一种描述结构化和半结构化数据的机制,提供了处理此类数据所需的一系列技术。像 XML 信息集等强大的提取功能将帮助我们使用 XML 技术更好地处理非文本数据,如文件系统、Windows® 注册表、关系数据库,甚至是编程语言对象。XML 使我们向实现通用的数据访问又迈进了一步。


 

 

版权所有:UML软件工程组织