JavaScript与XML

 使用XML具有很多好处,因此软件开发人员越来越喜欢XML。使用XML,使得许多Web开发工作比使用HTML时更加简单,XML还能完成许多简单的HTML所无法完成的任务。XML是一种功能强大的语言,它具有根据特定需要对标记语言进行模式化的能力。
  XML是一种以数据为中心的语言。XML不仅包含数据,而且还能使用具有语义的元素名称来描述数据。XML对文档自身的结构也能进行描述。与HTML不同的是,XML并不是一种格式定义语言,实际上,一个具有良好结构的XML文档是不包含任何格式定义元素的。通常这个概念被称之为“内容与样式的分离”,这正是XML的成功之处,它使得XML语言既简洁又强大。
  我们可以使用XML存储数据,就像使用一个数据库那样。实际上,XML非常适用于处理以结构化方式组织数据的庞大而复杂的文档。在XML中,我们可以定义文档的结构,实现我们自己的标记元素,并使用这些标记描述复杂的层次型数据。在XML文档中,我们不但可以定义文档结构,还可以定义所使用的标记元素,这使得XML成为了一种具有“自描述”能力的语言。也就是说,标记元素描述了标记所包含数据的含义,而文档结构的定义则描述了数据与数据之间的相互关系。
  XML的用途广泛,我们可以从远程服务器上获取以XML文件表示的数据。也许这个功能最著名的应用就是RSS和Atom,这两项技术都是基于XML的,用以实现Web网络的内容聚合。XML文档,或者其他类似于XML的文档,包含了对任何用户都可用的信息。Web站点或其他程序可以连接到远程服务器上,下载一份XML文档的副本,然后就可以将这些信息用在任何需要的地方。
  第三点,也是XML特别有用的地方是,XML可以用来在不兼容的系统之间传递数据。XML文档就是纯文本的文档,因此所有的操作系统都可以读取或写入XML文档,唯一需要的就是一个能理解XML语言及文档结构的应用程序。例如,Microsoft最近发布了Microsoft Office Open XML的详细规范,该文件格式被应用在Microsoft Office 2007中。Office XML格式的文件实际上是Zip形式的XML文件。因此,无论操作系统是Windows XP、Mac OS X、或者任何版本的Linux、以及任何其他的操作系统,只要具有了可以读取和生成XML文件的应用软件,就可以打开Office XML格式的Zip文件,并显示其中的数据。
14.2  XML基础
  与其他的文档格式相比,XML的优势在于XML详细声明了一个关于文档结构定义的协议,通过文档结构定义,使得XML文档具有了自描述性。例如,XML文档可用以描述某本书中的特定章节,它可以包含这一章的标题、小节和文本,而文本又可以进一步分为多个段落。为了正确地编写XML文档,我们需要牢固地掌握XML语言的基础知识。
理解XML的语法
  XML是一种简单的语言,它的语法和规则都是非常简单的。遵循本小节中所介绍的XML语言规范,就可以正确地创建XML文档。
  1. XML是一种格式良好的语言
  如果一个文档完全遵循了XML的语法规范,则该文档就是一个格式良好的文档。这些规范包括以下几点:
● 所有的元素都必须具有一个开始标记和一个对应的结束标记,对于空元素来说,也可以只在开始标记中包含一个表示关闭的斜杠。
● 根元素必须是封闭的,所有元素必须被正确地嵌套在根元素中。
  因为任何一个XML解析器都是根据XML规范来编写的,所以使XML文档具有良好的格式是非常重要的。XML是一种严格规范的语言,这意味着对于一个非格式良好的文档,任何遵循XML标准规范的XML解析器都不能正确读取和显示该XML文档。
  结束标记
  XML规范要求任何一个元素都必须具有一个开始标记和一个结束标记。这是XML与HTML之间的一个不同之处,在HTML中,某些元素可以不包含结束标记,如<img>和<br>元素。因此,当你使用了一个开始标记时,必须在所包含的数据之后使用一个对应的结束标记。
     <?xml version="1.0" encoding="iso-8859-1"?>
    
     <myElement>Some data go here</myElement>
  上面的例子演示了一个简单的XML文档。第一行代码包含了一个XML声明。该声明向应用程序说明了当前XML文档所使用的XML规范的版本。现在使用的XML规范的版本是1.0版本(1.1版本很快就将发布)。注意,XML声明以<?开始,并以?>结束。这两个标记表明其中包含的是一个XML声明指令。在本例中,该XML声明指令说明了XML文档所使用的XML规范的版本,即使用1.0版本的XML规范,并使用ISO-8859-1 (Latin-1/West European)字符集。
  注意:
  XML声明没有结束标记。
  在XML声明之后,可以看到一段文本包含在一对XML标记之中。第一个标记是myElement元素的开始标记,第二个标记则是对应的结束标记。XML是一种区分大小写的语言,因此,必须确保结束标记与开始标记是精确匹配的。如果在开始标记和结束标记之间不包含任何数据,该文档仍是一个格式良好的XML文档。例如下面的例子:
     <myElement></myElement>
  虽然在上面的标记中并不包含任何数据,但是这仍然是一个格式良好的XML元素。这种XML元素被称为空元素(empty element)。可以将类似的空元素简写为:
     <myElement />
  在XML解析器看来,上面这行简写的代码与前面那行代码是完全等价的。因此,XML的空元素都可以表示为上面的简写形式。
  注意:
  XML规范并不要求标记元素中必须包含数据。
  正确地嵌套元素
  多年以来,浏览器的开发商们一直努力地改进他们的浏览器,使得浏览器对于非格式良好的Web页面,也能正确地呈现和显示。因为Web的飞速发展来源于芸芸众生的参与,所以放宽浏览器的要求似乎并不是什么大的问题。但是如果用XML解析器来加载一个类似的HTML文档时,将会接二连三地报告一系列的错误。造成这些错误的罪魁祸首莫过于没有正确地嵌套元素。
  XML规范要求元素必须被正确地嵌套,而不能像在HTML中一样出现交错嵌套的情况。例如,下面的XML文档就是格式错误的XML文档:
     <?xml version="1.0" encoding="iso-8859-1"?>
    
     <myDogs>
         <name>Morgan</name>
         <name>Molly
     </myDogs></name>
  在上面的XML文档中,大部分元素标记的格式都是正确的,但是第二个<name/>元素的结束标记被错误地放在了<myDogs/>元素的结束标记之后。这正是交错嵌套标记的例子,任何一个XML解析器都将把这个错误的文档视为无效。必须在关闭外层标记之前,先关闭内层标记。
  只需遵循上面两条规范,就能轻松地编写出格式良好的XML文档。接下来,将进一步深入讨论XML的语法。
  2. 文档结构
  XML以一种结构化的方式来组织和保存数据。任何一个XML文档都必须至少具有一个元素。文档中的第一个元素称为“根元素(root element)”,或者称为文档元素(document element)。无论将其称为哪一种元素,这两个术语所表达的都是同一个含义。任何一个XML文档都必须具有一个根元素,而且有且只能有一个根元素。
  我们可以用计算机操作系统的目录结构来做一个类比。例如C盘就是一个根目录(C:),C盘中的每一个目录都是以根目录开始的。根目录可以包含许多个子目录,每一个子目录又可以包含多个下一级的子目录,依此类推。
  XML文档的结构与计算机的目录结构是非常类似的。XML文档以一个根元素开始,并从根元素开始构建整个文档。例如,对于下面的XML文档:
     <?xml version="1.0" encoding="iso-8859-1"?>
    
     <myDogs>
         <name>Morgan</name>
         <name>Molly</name>
     </myDogs>
  文档中的第一个元素是<myDogs/>元素,它就是该文档的根元素。在根元素之下,包含了两个名为<name/>的元素。我们可以根据需要,在文档中添加多个元素或者数据。对于一个XML文档中可使用元素的数量,并没有什么限制,但只需记住,一个XML文档中有且只能有一个根元素,整个文档都是从根元素开始构造的。
  3. XML元素
  XML使用元素来标记和描述文档中的数据。因此,当我们在创建自己的XML文档时,要确保元素能正确地描述其中包含的数据。下面是对前面dogs XML文档的一个简单扩展:
     <?xml version="1.0" encoding="iso-8859-1"?>
    
     <myDogs>
    <dog breed="Labrador Retriever">
      <name>Morgan</name>
    </dog>
    <dog breed="Labrador Retriever">
      <name>Molly</name>
    </dog>
     </myDogs>
  上面的文档包含了一些新的信息,并且文档的结构已经发生了改变。尽管文档的内容和结构已经发生了变化,但该文档仍然是一个格式良好的XML文档。每一个开始的XML标记都具有一个对应的结束标记,并且每一个元素的嵌套都是正确的。
  每一个XML文档的第一行都包含了一个XML声明。在本例中,它将该XML文档声明为一个遵循XML 1.0规范,并使用ISO-8859-1 (Latin-1/West European)字符集的XML文档。
  第二行则描述了该XML文档的根元素标记。在本例中是<myDogs>元素标记。它的含义是:“本文档的信息都包含在myDogs元素中”。
     <myDogs>
  接下来的一行定义了一个<dog/>元素,即根元素的一个子元素。<dog/>元素包含了dogs的相关信息。
     <dog breed="Labrador Retriever">
         <name>Morgan</name>
     </dog>
  显然,与上一小节中的简单XML文档相比,该XML文档包含了更为丰富的信息。新添加的<dog/>元素允许我们为每一个dog添加更多的详细信息。
  另外,在<dog/>元素中还添加了一个breed属性,breed属性包含了该dog的品种信息。在XML文档中,每一个元素都可以包含属性,这些属性可以作为该元素的参数传递给其他应用程序(在本例中,应用程序指的是诸如IE或Netscape之类的浏览器),但是,属性并不是元素内容的一部分。元素的属性包含在该元素的开始标记中,并且属性的值必须用一对引号括起来。某些开发人员不想创建子节点,并使用元素的属性来代替子节点。
  <dog/>元素还包含了一个名为name的子元素,用以保存dog的名字信息。
  第二个<dog/>元素包含了相同结构的信息:
     <dog breed="Labrador Retriever">
         <name>Molly</name>
     </dog>
  该XML文档的最后一行代码定义了根元素的结束标记。
     </myDogs>
  在上面的XML文档中,元素的名称及元素的属性很好地描述了所包含数据的含义。在阅读该XML文档时,我们很容易明白这些数据的意义,以及这些数据之间的关系。
  4. 字符数据
  XML中的字符数据可以是除了<字符之外的任何合法字符(Unicode字符集)。<字符是一个保留字,用以表示一个开始标记或者一个结束标记的起始。
  XML还定义了一些非常有用的实体引用,以表示那些在XML字符数据中的标记字符。在XML中提供了表14-1所示的实体引用:
表  14-1
实 际 字 符
实 体 引 用
>
&gt;
<
&lt;
&
&amp;
'
&apos;
  
  显而易见,对于字符数据来说,实体引用是非常有用的,如&lt;引用。其他的实体引用则可用在标记中,以代替那些XML语言中的保留字,否则将造成XML的混乱。例如下面的XML代码:
     <statement value = "She said, "Don't go there!"" />
  正确的代码应该使用实体引用,可将上面的代码改写为:
     <statement value = "She said, &quot;Don&apos;t go there!&quot;" />
  5. CDATA
  我们可以将任何位于XML元素标记之外的字符视为XML字符数据,而将任何位于XML元素标记之内的字符视为标记字符,这有时是一条很好的经验法则。但是,对于 CDATA标记块中的数据,则并非如此。在一个CDATA标记块中,所有的元素标记字符和实体引用都将被XML处理器忽略,仅仅将它们视为普通的字符数据。
  当我们想在XML文档中包含一大段带有特殊字符的数据,而又不想使用大量的实体引用时,CDATA标记块为我们提供了一个便利的容器。例如,当我们想在XML文档中包含一个XML片段作为某个元素标记的内容数据时,该怎么办呢?例如下面的XML代码:
     <example>
       &lt;document&gt;
         &lt;name&gt;mrs smith&lt;/name&gt;
         &lt;email&gt;mrssmith@herdomain.com&lt;/email&gt;
       &lt;/document&gt;
     </example>
  正如上面的代码所示,我们需要将所有开始标记和结束标记中的特殊字符(<和>字符)使用实体引用来表示,这不但使XML代码显得非常繁琐杂乱,而且难以阅读。
  为了避免这种不便,可以把这些字符数据放在一个CDATA数据块中,这样不管它看上去是一个标记还是一个实体引用,这些数据统统被当作普通字符进行处理。于是,上面的元素就可以改写为:
     <example>
    <![CDATA[
           <document>
       <name>mrs smith</name>
       <email>mrssmith@herdomain.com</email>
           </document>
    ]]>
     </example>
  6. 注释
  在XML文档中,有时我们希望XML处理器忽略对某些元素的处理(即将这些元素显示为普通的字符数据),而有时我们则希望XML忽略文档中的某些字符数据(即根本不显示)。这时就应该使用XML注释。
  注意:
  当使用默认的样式表时,XML注释将会被显示出来。这些文本称为注释文本。
  XML注释与HTML中的注释是非常类似的,在HTML中,使用<!-- 和-->语法来声明注释,在XML中声明注释的方法与此完全相同。下面的代码是一个有效的XML注释:
     <!--List Audioslave -->
     <name>Chris Cornell</name>
     <name>Tom Morello</name>
     <name>Timmy C</name>
     <name>Brad Wilk</name>
     <!-- End the names -->
  在使用XML注释时,请记住几个重要的规则。首先,在注释文本中绝不能包含有连字号(-)或者双连字号(--),否则可能造成XML处理器的混乱;其次,注释不能放在XML元素的开始标记或者结束标记中。因此,下面的XML代码是格式错误的XML代码:
     <name <!--The name --> >Tom Morello</name>
  另外,注释不能位于XML实体声明中,也不能放在XML声明之前。
  注意:
  在任何XML文档中,XML声明必须总是XML文档的第一条语句。
  如果需要的话,还可以使用注释标记将一组XML元素注释掉。例如对于下面的代码,除了Brad Wilk之外,包含其他名字的XML元素都已经被注释掉。
     <!-- don't show these names
     <name>Chris Cornell </name>
     <name>Tom Morello </name>
     <name>Timmy C</name>
     -->
     <name>Brad Wilk</name>
  当使用注释将一组XML元素从XML文档中注释掉时,必须确保其余XML文档仍然是一个格式良好的XML文档。
  
14.3  创建XML文档
  百闻不如一见,下面我们将实际地创建一个XML文档。XML是以数据为中心的标记语言,因此本例中需要使用一些数据,我们就以宠物狗为例吧。本例中的数据将包含下列字段:
● Name
● Age
● Breed
● Full blood
● Coat color
  使用这些数据字段,可以创建一个如下所示的文档结构:
     <?xml version="1.0" encoding="iso-8859-1"?>
    
     <myDogs>
    <dog breed="">
           <name></name>
           <age>
       <years></years>
       <months></months>
           </age>
           <fullBlood></fullBlood>
           <color></color>
    </dog>
     </myDogs>
  上面仅仅列出了基本的文档结构,实际的数据将在随后添加。下面我们说明一下该结构中的相关元素。
  注意:
  XML元素必须对所包含数据的含义具有一定的描述性。另外,必须记住XML是区分大小写的语言。因此,一个元素的结束标记必须与该元素的开始标记精确匹配。
     <?xml version="1.0" encoding="iso-8859-1"?>
  如上面的代码所示,第一行代码是XML的声明,该声明将告诉XML解析器,该XML文档使用的是XML 1.0版本标准,并使用ISO-8859-1 (Latin-1/West European)字符集。接下来的第一个元素就是该XML文档的根元素,即<myDogs/>元素。
     <myDogs>
     </myDogs>
  
  
  根元素是对整个XML文档的一个描述。任何看到这个文档的人都可以很容易地推断出该文档所包含的数据是关于宠物狗的。由于<myDogs/>元素是该XML文档的根元素,其他所有的元素都被包含在该元素中。
     <myDogs>
         <dog breed="">
         </dog>
     </myDogs>
  <dog/>元素是<myDogs/>元素的直接子元素,<dog/>元素包含了某只宠物狗的具体信息。该元素还包含一个名为breed的属性,该属性将用以表示这只宠物狗的品种。在<dog/>元素中,又包含了其他的子元素,用以包含这只宠物狗的其他方面的详细信息:
     <myDogs>
         <dog breed="">
           <name></name>
           <age>
               <years></years>
               <months></months>
           </age>
           <fullBlood></fullBlood>
           <color></color>
         </dog>
     </myDogs>
  其中,<name/>元素包含了该宠物狗的名字,<age/>元素则表示该宠物狗的年龄信息。由于年龄通常又包含了年数和月份数,因此<age/>元素又包含了两个子元素:<years/> 元素和<months/>元素。另外,<fullBlood/>元素将包含一个布尔值:yes或者no,以表示该宠物狗是否是纯种狗。如果该宠物狗是纯种狗,则<fullBlood/>元素所包含的值将是yes。最后一个元素<color/>将用以表示宠物狗毛皮的颜色。
  上面这个文档结构是一个格式良好的XML文档结构。下面我们将讨论如何定义一个有效的XML文档。
14.3.1  文档类型定义(DTD)
  如果在创建XML文件时产生了一个格式错误,则浏览器将提示错误发生在什么地方。但是对于与实际所包含数据有关的错误,浏览器将不会进行提示。但是毕竟人非圣贤,错误再所难免。
  在这一小节中,我们将介绍一个新的术语:XML文档的有效性。XML文档可以是结构良好的,也可以是有效的,或者不但是结构良好的,而且还是有效的。有效的XML文档不仅仅指的是格式良好的XML文档,而且还必须是遵循文档类型定义(Document Type Definition,DTD)的XML文档。DTD用以定义XML文档的结构信息。例如e-mail的例子,e-mail是具有结构的数据。一个e-mail包含了多个字段,包括To:(发送目标)、Subject:(主题)、以及body(邮件体)字段。另外,还可以包含其他可选字段,例如CC: 和BCC: 字段。此外,电子邮件程序还将自动为我们填写“From:(来自)”字段、以及发送日期和时间等字段。e-mail是如此地常用,除非是发送e-mail时产生了混乱,否则你可能从来没有注意到e-mail本身所包含的结构。e-mail所具有的这个结构使得e-mail易于阅读。如果一个程序想要处理e-mail(本质上e-mail是一种从网络下载下来的数据),则必须先理解e-mail所包含的结构,根据这个结构才能正确地解析e-mail中的数据。理解e-mail的结构,指的就是能正确地分析e-mail所包含的结构,并从中获取相应的数据,从而能对e-mail数据进行正确的解析。
  DTD文件定义了XML文件的元素标记及XML文档的结构。根据DTD的定义,我们就能理解和处理其他人根据同样的DTD所创建的XML文件。另外,如果一个XML文件是非格式良好的,或者传递了错误的数据给应用程序时,DTD还允许我们跟踪检查错误。关于DTD我们已经说了很多,下面就让我们来创建一个实际的DTD文件。
14.3.2  创建第一个DTD文件
  DTD文件的作用在于:
● 声明XML文档中的标记
● 声明这些标记的含义,即XML文档的结构
  那么如何来创建一个DTD文件呢?实际上,关于DTD的创建具有一个完整而详细的规范。但在本小节中,我们仅简要介绍一些与宠物狗的XML文件示例有关的DTD元素。
  打开一个文本编辑器,如Windows系统中的Notepad(记事本),建立一个名为mydogs.dtd的新文件,并输入如下所示的代码。下面的代码正是myDogs文档的DTD定义:
     <!-- The myDogs DTD -->
     <!ELEMENT myDogs (dog+)>
    
     <!-- The <dog/> section -->
       <!ELEMENT dog (name, age, fullBlood, color)>
       <!ATTLIST dog breed CDATA #REQUIRED>
       <!ELEMENT name (#PCDATA)>
       <!ELEMENT age (years, months)>
     <!-- The <age/> section-->
     <!ELEMENT months (#PCDATA)>
     <!ELEMENT years (#PCDATA)>
     <!-- END age section-->
       <!ELEMENT fullBlood (#PCDATA)>
       <!ELEMENT color (#PCDATA)>
       <!-- END <dog/> section -->
     <!-- END of myDogs DTD-->
  上面代码的第一行是一个XML注释。任何位于<!--和-->之间的内容都将被忽略。
     <!-- The myDogs DTD -->
  为代码编写注释是一个很好的习惯。在XML文档中,XML元素的声明具有如下所示的格式:
     <!ELEMENT elementName (content)>
  该声明用以定义文档中将要使用的元素。在上面的DTD定义中,我们定义了一个名为myDogs的元素,作为文档的根元素。在根元素myDogs中,可以包含多个<dog/>元素,因此,我们使用dog+进行定义。相应代码如下所示:
     <!ELEMENT myDogs (dog+)>
  下面这个注释说明了接下来将要定义的是<dog/>元素。
     <!-- The <dog/> section -->
  如果参考前面我们所设想的宠物狗XML文件的结构,可以看到<dog/>元素应该包含一个名为breed的属性,并且包含下列4个子元素:name、age、fullBlood和color子元素。
     <!ELEMENT dog (name, age, fullBlood, color)>
  一个子元素与下一个子元素之间具有一个逗号,这表明<dog/>元素中的这些子元素是具有严格顺序的。如果任何一个子元素未按DTD中定义的顺序出现,则该XML文档就是无效的。由于<age/>子元素本身又包含了两个子元素,因此还需要定义<age/>元素。下面的代码则定义了一个名为breed的属性:
     <!ATTLIST dog breed CDATA #REQUIRED>
  定义一个属性的方法与定义元素的方法非常类似,定义属性可以采用如下所示的格式:
     <!ATTLIST elementName attributeName attributeType defaultValue>
  DTD中属性的类型分为几种,但是最常用的是CDATA类型的属性。对于默认值来说,#REQUIRED用以告诉XML解析器,breed属性在每一个<dog/>元素中都必须出现。在DTD中也还有其他的默认值设置,但是#REQUIRED最适合本例的需要(毕竟,我们都想知道你的宠物狗是什么品种的,对吧?)。
  在#REQUIRED的前面使用了#号,另外在下面代码中#PCDATA之前也使用了#号,这是为了避免这些单词被解析为元素的名称。
  下面就是实际的元素类型定义。这些定义完全遵循前面我们所讨论的DTD定义格式。
   <!ELEMENT name (#PCDATA)>
     <!ELEMENT age (months, years)>
     <!-- The <age/> section-->
     <!ELEMENT years (#PCDATA)>
     <!ELEMENT months (#PCDATA)>
     <!-- END age section-->
     <!ELEMENT fullBlood (#PCDATA)>
     <!ELEMENT color (#PCDATA)>
     <!-- END <dog/> section -->
     <!-- END of myDogs DTD-->
  
  DTD就是这样定义的,这也是编写DTD最简单的方法。当我们在编写XML文档时,在XML文档中就可以通过<!DOCTYPE>声明来引用这个DTD文件。
14.3.3  加入数据
  我们已经知道了如何使一个格式良好的XML文档成为一个有效的XML文档。下面我们将在该XML文档中添加实际的数据。表14-2列出了我们将要使用的数据:
表  14-2
数 据 字 段
Dog 1
Dog 2
Dog 3
Name
Morgan
Molly
Casey
Age
10 months
8 years
6 years
Breed
Labrador Retriever
Labrador Retriever
Pomeranian
Full Blood
Yes
Yes
Yes
Color
Chocolate
Yellow
Brown
  
  我们可以打开任何一个纯文本编辑器,并创建如下所示的XML文档。
     <?xml version="1.0" encoding="iso-8859-1"?>
    
     <!DOCTYPE myDogs SYSTEM "myDogs.dtd">
    
     <myDogs>
   <dog breed="Labrador Retriever">
    <name>Morgan</name>
    <age>
      <years>0</years>
      <months>10</months>
    </age>
    <fullBlood>yes</fullBlood>
    <color>chocolate</color>
   </dog>
   <dog breed="Labrador Retriever">
    <name>Molly</name>
    <age>
           <years>8</years>
           <months>11</months>
    </age>
    <fullBlood>yes</fullBlood>
    <color>yellow</color>
   </dog>
   <dog breed="Pomeranian">
         <name>Casey</name>
        
        
         <age>
           <years>6</years>
           <months>2</months>
         </age>
         <fullBlood>yes</fullBlood>
         <color>brown</color>
   </dog>
     </myDogs>
  将上面的代码保存为mydogs.xml文件。在该XML文档中并没有多少新增的内容。该文档的结构与上一小节中我们用DTD定义的文档结构完全匹配。但是,相应的数据生成了多个<dog/>元素。另外,在该XML文档中,添加了对前面定义的DTD文件的引用。即添加了如下所示的<!DOCTYPE>声明:
     <!DOCTYPE myDogs SYSTEM "myDogs.dtd">
  !DOCTYPE指令告诉了XML解析器,在该XML文档中需要引用一个DTD文件,该DTD文件定义了当前XML文档的结构。随后列出的是该XML文档根元素的名称,即 myDogs。SYSTEM指令则告诉XML解析器,该XML文档使用了一个外部的DTD,该DTD是一个独立于当前XML文档的文件。最后,"myDogs.dtd"则指明了该DTD文件的位置。如果该DTD文件位于一个Web服务器上,则该DTD文件的位置将是一个类似于http://myserver/myxmlstuff/myfile.dtd的URI。如果该DTD文件与当前XML文档在同一个目录中,则只需要直接引用DTD文件的名称即可。
  如果不想使用一个外部的DTD文件,而是使用一个包含在XML文档中的内部DTD,则该XML文档将具有如下所示的结构:
     <?xml version="1.0" encoding="iso-8859-1"?>
    
     <!DOCTYPE myDogs [
     <!-- The myDogs DTD-->
     <!ELEMENT myDogs (dog+)>
     <!-- The dog section -->
     <!ELEMENT dog (name, age, fullBlood, color)>
       <!ATTLIST dog breed CDATA #REQUIRED>
       .........(rows removed for demonstration).........
     <!-- END of myDogs DTD-->
     ]>
     <myDogs>
  无论采用哪一种方式,XML解析器都将使用DTD来检查XML文档的有效性。我们可以在浏览器中加载mydogs.xml文件。在IE 7浏览器中,将看到一个如图14-1所示的页面。
  对于Firefox浏览器,加载文档后的页面将如图14-2所示。

图  14-1

图  14-2
  如果在XML文档中存在错误,即使是一个很小的错误,浏览器将显示错误信息,如图14-3或者14-4所示。

图  14-3

图  14-4
  在该XML文档中我们故意设置了一个错误,即将结束元素</myDogs>故意错误地写成</mydogs>。
  浏览器可以用于显示XML文档,它将检查XML文档是否是一个格式良好的文档。注意,根据所使用的浏览器的不同,XML文档在浏览器中的显示效果也不相同。IE浏览器和Firefox浏览器都使用XSLT来格式化XML文档的显示(关于XSLT的内容本章稍后将进行介绍),但是其他浏览器则可能有所不同。
  注意:
  Firefox浏览器并不能检验XML文档的有效性。IE浏览器默认情况下也不对XML文档的有效性进行检查,但是可以下载一个工具来检查XML文档的有效性。该工具就是Internet Explorer Tools for Validating XML and Viewing XSLT Output,可以从以下网址下载该工具:www.microsoft.com/downloads/details.aspx?FamilyID=d23c1d2c-1571-4d61-bda8- adf9f6849df9&DisplayLang=en。
  另外,如果在浏览器中查看XML文档,如图14-1所示,可以看到在XML元素开始标记之前具有一些红色的破折号。单击某个破折号就可以将该层次结构中对应的文档部分折叠起来。对于包含子节点的元素,都可以将该节点折叠显示或者展开显示。因此,我们可以将某个<dog/>元素折叠显示,也可以将整个文档都折叠显示。
  IE 5+浏览器和Firefox浏览器之所以能够显示XML文档,并使之按某种颜色模式显示,或者还可以在浏览器中进行元素的折叠或展开操作,这是由于浏览器为那些没有引用任何样式表的XML文档提供了一个内建的默认样式表。XML文档中的样式语言被称为可扩展样式语言(Extensible Stylesheet Language,XSL)。
14.4  改变XML的显示外观
  现在我们已经知道了如何使用XML来定义数据,以及如何在浏览器中显示这些数据,但是这时浏览器只是以一种粗糙的方式来显示原始数据,并未对显示的样式进行相应的加工和处理。在这一小节中,将介绍如何为浏览器中显示的XML数据添加显示样式。在第12章中,我们已经对CSS(层叠样式表)技术进行了介绍,因此这一小节将不再介绍CSS的相关内容,而是直接介绍如何将CSS应用于XML数据的样式设置。
14.4.1  样式表与XML
  使用CSS具有很多的好处:
● CSS实现了内容与显示样式的分离,这使得文档更加清晰可读。
● 一个CCS样式可供多个地方引用。
● 只需修改某个CSS样式的定义,就可以修改所有引用了该样式的元素的显示效果。
● 使用CSS可以将同一份数据以不同的显示样式进行呈现。
  对于样式表来说,所有的样式规则都被定义在一个层叠样式表文件中,该层叠样式表文件则被链接到源文件中。因此,我们所定义的样式规则必须与XML的标记相对应。
  下面我们创建一个名为mydogs.css的样式表文件,并输入如下所示的代码:
     dog
     {
         margin: 15px;
         display: block;
     }
    
     name
     {
         display: block;
         font: bold 18pt Arial;
     }
    
     age
     {
         display: block;
         color: red;
     }
    
     fullBlood
     {
         display: none;
     }
    
     color
     {
         display: block;
         font-style: italic;
     }
  在上面的样式表中,定义了相应的样式规则以匹配XML文档中对应的元素,即dog、name、age、fullBlood和color元素。在XML文档中,这些元素包含了实际要显示的数据。通过第12章的学习我们已经知道,元素的名称可以作为CSS的选择器,以使该CSS样式应用在与选择器相匹配的元素之上。
  在一个CSS样式中,真正起作用的是该样式中定义的CSS属性,这些属性位于大括号({ })中。这些属性将被应用于与选择器相匹配的元素之上。例如我们为dog元素定义的样式就包含了两个属性:margin属性和display属性。margin属性是我们遇到的一个新样式属性,该属性表示围绕着元素的外边框。如果将margin属性设置为0px,则围绕着元素的外边框的宽度将是0像素,如果将margin属性设置为15px,则元素周围将有一个15像素宽的外边框。在本例中,我们将margin属性设置为15px,以强调一只宠物狗数据的开始和结束。
  除了fullBlood之外(实际上,fullBlood样式将元素设置为根本不显示),其余的元素样式都被设置为以块元素的方式显示:display: block。name元素的文本被设置为bold 18pt Arial(即粗体、18pt,Arial字体),而age元素的文本则被设置为红色,另外,color元素的字体样式则被设置为斜体。
  现在,我们具有了两个文件:mydogs.xml文件和mydogs.css文件。我们还需要在XML文档中,引用所定义的CSS文件。打开mydogs.xml文件并在XML声明之后添加下面这行代码,以指定对CSS文件的引用,并将修改后的文件保存为mydogs_css.xml文件。
     <?xml-stylesheet href="mydogs.css" type="text/css"?>
  当我们在IE浏览器中打开该XML文件时,将看到一个如图14-5所示的页面。

图  14-5
  如果在Firefox浏览器中打开该XML文件,则将看到一个如图14-6所示的页面。

图  14-6
  在图14-6中,我们可以看到相应的数据已经被显示了出来,但是令人遗憾的是,并没有任何说明来描述这些数据所代表的含义。当然,由于数据是我们自己编写的,因此我们知道这些数据的意义,但是对于浏览页面的其他人来说则不然。虽然CSS可以使页面显示得更美观,但是如果我们想为数据添加相应的说明,那又该怎么办呢?
14.4.2  可扩展样式语言(XSL)
  在下面这一小节中,我们将介绍如何使用XSL(Extensible Stylesheet Language,可扩展样式语言)中的XSLT(Extensible Stylesheet Language Transformations,可扩展样式转换语言)将一个XML文档格式化为一个HTML文档。
  1. XSLT是什么
  XSLT是一种基于模板的样式转换语言,它可以将XML文档中的内容进行重新构造,并转换为我们所需要的格式。XSLT转换可以允许不同种类的应用程序交换数据。使用XSLT可以使同一份源文档生成多个不同的视图,从而使Web站点的内容可以在多种设备上显示。
  XSLT是一种声明性的样式转换语言,它定义了相应的元素和属性来处理XML中的数据。通过XSLT的指令集,可以从其他文档中抽取相应的内容,或者创建新的元素和属性。更常见的情况是把抽取内容与创建新的元素或属性结合起来使用。
  XSLT 1.0的转换需要两个文档(一个是XML源文档,另一个是XSLT样式表),转换的结果将生成一个新的文档(在即将发布的XSLT 2.0中则可以创建多个输出文件)。当把一个XSLT样式表应用于一个XML文档时,转换的处理过程就开始了,转换的结果是生成一个新的文档树,通常情况下,转换的结果是一个新的XML文档或者HTML文档(如图14-7所示)。
  注意:
  XSLT是一种功能强大的样式转换语言,本质上,它可以将XML文档转换为任何基于文本的语言或其他格式的文本。
  与CSS类似,XSLT也是通过转换规则来构建的。某一条转换规则将对匹配的元素实行相应的转换。
   2. XSLT的模板规则是什么
  一个XSLT文件包含了多个转换模板,一个转换模板包含了如下的定义:
● 选择元素:从源文档树中选择元素的标准。
● 转换指令:将所抽取的内容进行再构造,以创建结果文档树的指令。
  模板规则是构建XSLT转换的关键。一个模板规则包含两个部分:模式和转换模板。模式(通常情况下为一个元素名称)用以在源文档树中匹配相应的元素,与模式匹配的元素将被执行转换操作。而转换模板则定义如何对匹配的节点进行转换操作。

图  14-7
  每一个转换模板都将在结果树中构造一个标记和内容的片段。当所有的片段都按指定的顺序结合起来之后,将形成一个新的文档,一个XSLT转换的结果树就创建完成了。
  下面我们将通过一个具体的实例,进一步介绍XSLT模板的转换规则。
  3. XSLT模板实例
  与任何XML文档一样,XSLT样式转换文档也必须先进行XML版本声明。例如:
     <?xml version="1.0" encoding="iso-8859-1"?>
  接下来,还应该声明XSLT命名空间(namespace)的前缀。XSLT的命名空间前缀用以在XSLT样式表中,将具有相同元素名、不同命名空间的元素区分开来,例如,区分包含在模板规则中的HTML元素。
  XSLT样式表的根元素为:xsl:stylesheet或者xsl:transform。XSLT的命名空间前缀应在根元素中进行声明。
  在根元素和xsl命名空间前缀声明之间,必须具有一个XSLT的版本属性声明。
  XSLT的命名空间是由唯一的URI值来标识的(该URI为http://www.w3.org/1999/XSL/ Transform),并不是通过xsl前缀来标识。例如下面的代码:
     <?xml version="1.0" encoding="ISO-8859-1"?>
     <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/
     Transform">
  现在,已经声明了命名空间前缀,接下来我们就可以创建一些模板规则,以将源文档中的内容转换为一个HTML表格。位于模板中的HTML标记片段为XSLT处理程序提供了一个对源内容进行重新构造的模板。
  xsl:template元素用以定义一个模板规则。该元素match属性的值是一个XPath表达式,该XPath表达式用以从源文档中选择匹配的元素,以进行转换处理。文档的第一个模板总是与“/”进行匹配,它表示文档的根元素。
     <?xml version="1.0" encoding="utf-8"?>
    
     <xsl:stylesheet version="1.0"
         xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    
     <xsl:template match="/">
       <html>
     <head>
       <title>Review Of My Dogs</title>
     </head>
     <body>
       <h4>List Of My Dogs</h4>
       <table width="100%" border="1">
        <thead>
          <tr>
                       <th>Name</th>
                       <th>Breed</th>
                       <th>Age</th>
                       <th>Full Blood</th>
                       <th>Color</th>
          </tr>
        </thead>
        <tbody>
          <xsl:apply-templates/>
        </tbody>
       </table>
     </body>
       </html>
     </xsl:template>
  apply-templates元素通知XSLT处理程序查找另一个模板规则,并在XSLT样式表结构中该apply-templates元素的位置处应用该模板规则。将每一个模板规则的转换结果组合起来,就形成了一个完整的转换结果。
  下面这个模板用以匹配和处理XML文档中的每一个<dog/>元素。该模板将为每一个<dog/>元素创建一个表格行,直到所有的<dog/>元素处理完毕。
 <xsl:template match="dog">
   <tr>
         <td>
       <strong>
         <xsl:value-of select="name" />
       </strong>
         </td>
         <td>
       <xsl:value-of select="@breed" />
         </td>
         <td>
       <xsl:apply-templates select="age" />
         </td>
         <td>
       <xsl:value-of select="fullBlood" />
         </td>
         <td>
       <xsl:value-of select="color" />
         </td>
   </tr>
 </xsl:template>
  值得注意的是,在上面的代码中:value-of元素也使用了一个select属性,该属性用以从源文档中选取需要的内容,以创建新的结果文档。另外,在上面的模板中,我们还使用了<xsl:apply-templates select="age" />指令,该指令的select属性的值为"age",这表示XSLT处理程序需要查找另一个匹配和处理<age/>元素的模板。
     <xsl:template match="age">
         <xsl:value-of select="years"/> years
         <xsl:value-of select="months"/> months
     </xsl:template>
     </xsl:stylesheet>
  上面的模板将选取<age/>元素,并获取<age/>元素的子元素的值,即<years/>元素和 <months/>元素的值。为了说明值的含义,该模板在相应元素的值之后添加了years和months这两个单词作为说明。这使得任何阅读这些信息的人很容易明白这些值所代表的含义是什么。
  完整的XSLT文件如下所示:
<?xml version="1.0" encoding="utf-8"?>

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

<xsl:template match="/">
     <html>
       <head>
         <title>Review Of My Dogs</title>
       </head>
       <body>
         <h4>List Of My Dogs</h4>
         <table width="100%" border="1">
      <thead>
               <tr>
                   <th>Name</th>
                   <th>Breed</th>
                   <th>Age</th>
                   <th>Full Blood</th>
                   <th>Color</th>
               </tr>
      </thead>
      <tbody>
               <xsl:apply-templates/>
      </tbody>
         </table>
       </body>
     </html>
</xsl:template>

<xsl:template match="dog">
  <tr>
       <td>
     <strong>
             <xsl:value-of select="name" />
     </strong>
       </td>
       <td>
     <xsl:value-of select="@breed" />
       </td>
       <td>
     <xsl:apply-templates select="age" />
       </td>
       <td>
     <xsl:value-of select="fullBlood" />
       </td>
       <td>
     <xsl:value-of select="color" />
       </td>
  </tr>
</xsl:template>

<xsl:template match="age">
  <xsl:value-of select="years"/> years
  <xsl:value-of select="months"/> months
</xsl:template>

</xsl:stylesheet>
  请将该文件保存为mydogs.xsl。
  4. 如何将XML文档链接到XSL样式表
  将XML文档链接到样式表需要使用XML处理器指令,本章前面曾介绍过如何将XML文档链接到CSS样式表,将XML文档链接到XSL样式表的方法与之非常类似。实际上,除了type属性的取值不同之外(即text/css或者text/xsl),二者的语法完全相同。
  下面的代码比较了将XML文档连接到CSS和XSL的处理器指令,其中,仅有type属性的取值不同。
     <?xml-stylesheet type="text/xsl" href="mydogs.xsl"?>
     <?xml-stylesheet type="text/css" href="mydogs.css"?>
  在XML文档中,引用样式表的指令应该放在文档的序言位置(即位于XML声明之后,根元素之前)。
  下面我们将修改mydogs_css.xml文件,以添加对mydogs.xsl样式表文件的引用。打开mydogs.xsl文件,并在文件开头处添加如下所示的代码:
     <?xml version="1.0" encoding="iso-8859-1"?>
    
     <?xml-stylesheet type="text/xsl" href="mydogs.xsl"?>
    
     <!DOCTYPE myDogs SYSTEM "mydogs.dtd">
    
     <myDogs>
     <dog>
     ...
     ....
  在上面的代码中,首先删除了对CSS文件mydogs.css的引用,并添加了对mydogs.xsl样式表文件的引用,对文档中其余的部分未做任何变动。将修改后的文件保存为mydogs_xslt.xml文件。在IE浏览器中加载该页面,将看到一个如图14-8所示的页面。

图  14-8
  如果在Firefox浏览器中加载该页面,则如图14-9所示。
  
图  14-9
14.5  使用JavaScript操作XML
  在前面的章节中,我们已经学习了如何操作DOM,这使得我们已经具备了在浏览器中操作XML文档所需的绝大部分知识。尽管在每一个新版本的浏览器中,对XML JavaScript的支持越来越好,但是对XML JavaScript的支持仍未完美,许多跨浏览器的问题依然存在。正是由于这样的原因,在这一小节中,我们将把注意力集中在对于IE 5.5+浏览器(仅对Windows平台上的IE浏览器而言,Mac版本的IE浏览器并不支持XML)、Firefox浏览器和Opera浏览器跨浏览器脚本的兼容性问题上。这些浏览器对XML JavaScript的支持都有了很大的改进。
  首要的任务是如何读取XML文档。由于IE浏览器在如何读取XML文档上与其他浏览器之间存在较大的差异,因此,如何读取XML文档是解决跨浏览器兼容问题的关键所在。Firefox浏览器和Opera浏览器采用了遵循标准规范的方法来读取XML文档,而IE浏览器则采用了更加简单和容易理解的方法来读取XML文档。但是,一旦XML文档被加载之后,IE浏览器与Firefox和Opera浏览器之间对XML文档操作的差异就变得很小了,尽管如此,Microsoft还是在其XML具体实现中添加了许多非常有用(但不是标准)的扩展。
  
  注意:
  Safari 2浏览器也提供了对XML的支持,但是在Safari 2浏览器中,加载XML文档的方法实现与IE、Firefox浏览器和Opera浏览器中的实现完全不同,Safari 2浏览器要求使用一个称为XMLHttpRequest的对象,我们将在第16章中介绍这个对象。
14.5.1  在IE浏览器中获取XML文档
  IE浏览器依靠ActiveXObject()对象和MSXML库来获取和打开XML文档。在IE浏览器的脚本中,可以使用大量的ActiveX对象。要创建一个ActiveX对象,只需简单地调用ActiveXObject()构造函数,并传入一个包含ActiveX对象版本信息的字符串作为参数即可。例如下面的代码:
     var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
     xmlDoc.load("myfile.xml");
  在上面的代码中,通过将ActiveX对象的版本字符串"Microsoft.XMLDOM"传递给ActiveXObject()构造函数,创建了一个XML DOM对象,通过该XML DOM对象就可以操作XML文档了。在创建了XML DOM对象之后,就可以使用load()方法来加载一个指定的XML文档。在上面的代码中,我们加载了一个名为myfile.xml的XML文档。
  Microsoft MSXML library具有多个版本,每一个新版本都提供了比前一个版本更多的特性和更好的性能。但是,在使用这些版本之前,用户计算机上必须已经安装了这些版本的Microsoft MSXML library,版本选择的代码可以会变得比较复杂。因此,Microsoft建议只需检查两个版本的MSXML库。这两个版本是:
● Msxml2.DOMDocument.6.0
● Msxml2.DOMDocument.3.0
  在创建一个XML DOM对象时,我们总是希望使用最新版本的MSXML库。下面的代码可以用以选择当前可用的最高版本的MSXML库。
function createDocument()
{
  //Temporary DOM object.
  var xmlDoc;
  
  //Create the DOM object for IE
  if (window.ActiveXObject)
  {
   var versions =
    [
    "Msxml2.DOMDocument.6.0",
    "Msxml2.DOMDocument.3.0"
    ];
   
   for (var i = 0; i < versions.length; i++)
   {
    try
    {
         xmlDoc = new ActiveXObject(versions[i]);
         return xmlDoc;
    }
    catch (error)
    {
         //do nothing here
    }
   }
  }
  //no version was found; return null
  return null;
}
  上面的代码定义了一个createDocument()函数。在该函数中的第一行,定义了一个xmlDoc变量。该变量是一个临时变量,用以保存所创建的XML DOM对象。在接下来的if语句中,通过对象检测技术,检查了window.ActiveXObject对象是否存在,以判断当前浏览器是否是IE浏览器。如果检测条件为true,则创建一个名为versions的数组,并且把该数组初始化为Microsoft建议的两个版本的MSXML库。
     var versions =
     [
     "Msxml2.DOMDocument.6.0",
     "Msxml2.DOMDocument.3.0"
     ];
  数组元素初始化的顺序是非常重要的。由于我们希望尽量使用最新版本的MSXML库,因此应该先检测最新版本,并把最新MSXML库的版本字符串放在索引为0的数组元素中。
  接下来,使用了一个for循环来遍历versions数组。在该for循环中是一个try...catch语句。
     for (var i = 0; i < versions.length; i++)
     {
     try
     {
     xmlDoc = new ActiveXObject(versions[i]);
     return xmlDoc;
     }
     catch (error)
     {
         //do nothing here
     }
     }
  在try语句块中,如果ActiveXObject对象的创建失败,则代码的执行流将转移到catch语句块。在catch语句块中,则不做任何处理。执行完catch语句之后将进入下一轮循环,循环变量i自增1之后,versions[i]将是低版本的MSXML库字符串,代码将使用另一个版本字符串来创建ActiveXObject对象。如果每一个MSXML库字符串都失败了,则代码将退出循环,并返回一个null值。可以按以下方式使用createDocument()函数:
     var xmlDoc = createDocument();
  通过createDocument()函数,可以非常容易地创建最新版本的MSXML XML DOM对象。
14.5.2  如何判断XML文档何时被加载完成
  在操作XML文档之前,首先必须确定该XML文档是否已经被完全加载到客户端的浏览器中。否则,每次浏览页面时可能造成不可预知的结果,另外,在XML文档还未完全下载完成之前的任何时候,执行JavaScript脚本都将可能造成JavaScript脚本错误。幸运的是,我们可以检测XML文档的当前下载状态,以确定XML文档是否已经下载完毕。
  有两种载入XML文档的模式,即同步方式和异步方式。对于XML DOM对象,可用async属性来设置文档的载入方式,以决定浏览器在指定的XML文档下载完之前,是继续等待直到XML文档下载完,还是无须等待,继续下载和处理页面其余的部分。async属性代表的是“异步(asynchronous)”,默认情况下,async属性的值为true,浏览器将继续处理和呈现其后的页面内容,或者继续执行其后的JavaScript代码,无须等待XML文档被完全下载完。如果要将XML文档设置为同步方式载入,只需将async属性设置为false即可。当XML文档以同步方式载入时,浏览器将先下载该XML文档,直到XML文档完全载入之后,才继续执行JavaScript代码,或者继续载入页面的其他部分。
     var xmlDoc = createDocument();
     xmlDoc.async = false; //Download XML file first, then load rest of page.
     xmlDoc.load("myfile.xml");
  设置async属性是非常简单的,但使用async属性并不是毫无缺陷的。当把async属性设置为false时,IE浏览器将暂停页面的执行,直到连接到指定的XML文档源并完全载入了指定的XML文档之后,才会继续执行。但是当浏览器在连接网络或者下载XML文档时出现了故障或问题,则该页面将被一直挂起。因此,最好将async属性设置为true,即以异步方式加载XML文档。在异步方式下,我们可以通过onreadystatechange事件处理器和readyState属性来判断XML文档是否已经完全载入。
  在IE浏览器中,XML DOM对象和很多HTML对象都具有readyState属性,用以返回对象当前的加载状态。表14-3列出了readyState属性可能的值:
表  14-3
readyState属性的返回值
描    述
1
对象正在初始化,尚无任何可读的数据,正在载入数据(loading)
2
数据已经被载入并解析为DOM对象(loaded)
3
部分DOM对象的数据已经读取并解开,因此DOM对象模型已经可用。但是完整的对象数据仍然不可读(interactive)
4
DOM对象已经完全载入,XML文档的内容已经完全解析为DOM对象(completed)
  这里,我们所关注的readyState属性是最后一个属性,即readyState属性为4时的情形。当readyState属性为4时,表示XML DOM对象已经完全加载完毕。要想引用readyState属性,只需将XML DOM对象的onreadystatechange事件处理器设置为一个事件处理函数,当每次readyState属性改变时,都会触发XML DOM对象的readystatechange事件。
     //The function to handle the onreadystatechange event.
     function xmlDoc_readyStateChange()
     {
       //Check for the readyState. If it's 4, it's loaded!
       if (xmlDoc.readyState == 4)
       {
           alert("XML file loaded!");
       }
     }
    
     var xmlDoc = createDocument();
     xmlDoc.onreadystatechange = xmlDoc_readyStateChange;
    
     xmlDoc.load("myfile.xml");
  在上面的代码中,首先创建了一个名为xmlDoc_readyStateChange()的函数。该函数用以处理DOM对象的readystatechange事件。在xmlDoc_readyStateChange()函数中,检查readyState属性的值是否为4。如果是,则表示XML文档已经完全加载完毕,并弹出一个显示“XML file loaded!”的对话框。在该函数之后,使用createDocument()方法创建了一个XML DOM对象,并将该对象保存在变量xmlDoc之中。然后将xmlDoc对象的onreadystatechange事件处理器设置为xmlDoc_readyStateChange()函数。最后一行代码则加载了myfile.xml文件。
14.5.3  如何在Firefox和Opera浏览器中加载XML文档
  由于Firefox和Opera浏览器更多地以遵循标准为中心,所以在Firefox和Opera浏览器中,加载XML文档的方法与在IE中加载XML文档的方法略有不同。在Firefox和Opera浏览器中,加载XML文档不再需要使用类似于IE浏览器中的ActiveX外接式组件,DOM已经成为了Firefox、Opera浏览器和JavaScript实现的一部分。在Firefox和Opera浏览器中,要加载一个XML文档,可使用如下所示的代码:
     var xmlDoc = document.implementation.createDocument("","",null);
     xmlDoc.load("myfile.xml");
  在上面的代码中,使用document.implementation对象的createDocument()方法创建了一个空的DOM对象。在创建了DOM对象之后,使用了DOM对象的load()方法来加载myfile.xml文档。Firefox和Opera浏览器都支持使用以上的方法来加载XML文档。
14.5.4  如何判断XML文档已经加载完成
  与IE浏览器非常类似,Firefox和Opera浏览器都支持async属性,可用async属性将文档的载入方式设置为同步方式或者异步方式。在Firefox和Opera浏览器中,XML文档的同步载入方式与IE浏览器中是完全相同的。但是,当使用异步方式载入XML文档时,情况则有所不同。
  在异步方式下,当浏览器检测XML文档的加载状态时,Firefox和Opera浏览器与IE浏览器采取了不同的实现方式。实际上,Firefox和Opera浏览器都没有类似于IE浏览器中的readyState属性来检测文档的加载状态。但是,Firefox和Opera浏览器提供了一个XML DOM对象的onload事件处理器,当XML文档被加载完毕并且XML DOM对象已经可以使用时,将触发onload事件处理器的执行。
     //Handles the onload event
     function xmlDoc_load()
     {
         alert("XML is loaded!");
     }
    
     var xmlDoc = document.implementation.createDocument("","",null);
     xmlDoc.onload = xmlDoc_load;
     xmlDoc.load("myfile.xml");
  上面的代码将按异步方式加载XML文档myfile.xml。当XML文档被加载完毕之后,将触发XML DOM对象的load事件,并调用xmlDoc_load()事件处理函数,将一条XML is loaded!的信息显示给用户。
14.5.5  如何跨浏览器读取XML文档
  由于在不同的浏览器创建XML DOM对象的方法是不同的,因此我们需要找到一种跨浏览器的解决方案。通过浏览器对象检测技术,就能很容易地判断用户当前所使用的是何种类型的浏览器,因此,以跨浏览器的方式来创建XML DOM对象并非难事。实际上,只需简单地修改前面我们所创建的createDocument()函数,添加对Firefox浏览器和Opera浏览器的支持即可。相应代码如下所示:
     function createDocument()
     {
         //Temporary DOM object.
         var xmlDoc;
        
         //Create the DOM object for IE
         if (window.ActiveXObject)
         {
      var versions =
      [
      "Msxml2.DOMDocument.6.0",
      "Msxml2.DOMDocument.3.0"
      ];
      
      for (var i = 0; i < versions.length; i++)
      {
               try
               {
               xmlDoc = new ActiveXObject(versions[i]);
               return xmlDoc;
               }
               catch (error)
               {
                   //do nothing here
               }
      }
         }
         //Create the DOM for Firefox and Opera
         else if (document.implementation && document.implementation.createDocument)
         {
      xmlDoc = document.implementation.createDocument("","",null);
      return xmlDoc;
         }
         //no version was found; return null
         return null;
     }
  在上面的代码中,以灰色背景突出显示的部分就是新添加的代码,这部分代码用以处理Firefox和Opera浏览器的情形。当浏览器是Firefox和Opera时,使用document.implementation.createDocument()方法来创建XML DOM对象,并将该XML DOM对象返回给调用方。这个新的createDocument()函数使用起来也非常简单,而且该函数现在具有跨浏览器的功能。例如,我们可以按下面的方式使用createDocument()函数:
     var xmlDoc = createDocument();
     xmlDoc.async = false;
     xmlDoc.load("myfile.xml");
14.5.6  显示每日信息
  现在我们已经知道了如何加载XML文档,下面我们将创建一个包含XML的JavaScript应用程序,在该程序中,引用了一个XML文档,以向用户显示每日信息。
  首先,我们需要创%

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值