使用XSL样式表来显示XML文件

来源:互联网 发布:仓库入库软件 编辑:程序博客网 时间:2024/05/19 01:08
  在本章中,你将学习本书中所介绍在微软Internet Explorer 5 浏览器中显示XML 文件的最后方法:以延伸样式表语言撰写的样式表。就像在第七章中介绍过的串接样式表(CSS),XSL 样式表被链接至XML 文件,并告诉浏览器如何显示XML 资料,让你可以直接在浏览器中开启XML文件而不必使用中继的HTML 网页。
    然而,就显示XML 文件而言,XSL 样式表的确比串接样式表来得更具威力且更富弹性。当串接样式表仅仅允许你指定每个XML 元素的格式时,XSL 样式表还提供了完整的输出控制权。特别是,XSL 准许你精确地挑选你想显示的XML 数据,利用各种顺序或协议来显示这些资料,并且可以自由地修改或新增信息。XSL 提供你对所有XML 组件(像元素、属性、批注和处理指令)的控制权,构成元素的权力,让你轻易排序和筛选XML 中的数据,让你可以轻松地区分与过滤这些XML 数据,允许你在样式表中含括script 程序,并且提供一组有用的方法让你可以呼叫处里这些信息。
    本章中介绍的XSL 样式表的基本形态,会选择性地将XML 文件转换成HTML 格式,让浏览器处理并显示其内容。因此XSL 样式表提供你运用HTML 的完整格式安排与丰富功能特性的的能力,除此之外XSL 本身也提供了数据存取和转换的能力。
    然而,XSL 比CCS 来得复杂且难学,而且还需要具备HTML 的相关知识。它是一种比CCS 还新颖的技术,而且在目前的浏览器中,被支持的程度尚低,且较不一致。
提示
    本章只介绍XSL 基本知识。你可以从网站上学习更多有关XSL 的强大技术和这些技术的变革。你可以在下列由国际因特网协会(W3C)所提供的网站中,看到XSL 的官方规格文件的内容。网站分别是位于 http://www.w3.org/TR/WD-xsl 中的<Extensible Stylesheet Language (XSL)Version 1.0>部分,与位于 http://www.w3.org/TR/WD-xslt 中的<XSL Transformations (XSLT)
Version 1.0>部分。要获得更多有关Internet Explorer 5 对XSL 的支持信息,请参看下列由微软MSDN 提供的网站:位于 http:// msdn.microsoft.com/xml/xslguide/default.asp 中的<XSLDeveloper's Guide>内容与位于网页 http://msdn.microsoft.com/xml/reference/xsl/start.asp 中的<XSL Reference>内容。

使用XSL 样式表-基本知识

    利用XSL 样式表来显示XML 文件有两个基本步骤:
    建立一个XSL 样式表档案 。XSL 是XML 的应用程序。意即,XSL 样式表是一个遵守XSL规则的格式正确的XML 文件。就像任何XML 文件一样,XSL 样表是由纯文字组成,所以你可以使用你最熟悉的文字编辑器来编辑XSL 样表。接下来将解释如何编写不同形态的XSL 样式表。
    将XSL 样式表链接至XML 文件 。虽然你利用XML 来建立XML 文件和XSL 样式表,但它们还是被储存在个别的档案中:XML 文件档案(扩展名为.xml),与XSL 样式表档案(扩展名为.xsl)。借着在这份文件中含括xml-stylesheet 处理指令,你可以将XSL 样式表链接至XML文件。使用方式有下列数种型态:
<?xml-stylesheet type="text/xsl" href=XSLFilePath?>
    这里的XSLFilePath 是一个引号包围的URL,指出样式表档案的所在位置。可以是完整的URL,如下所示:
<?xml-stylesheet type="text/xsl"
href="http://www.my_domain.com/Inventory.xsl"?>
    然而,更常见的情况是,你可以使用部分的URL 来指出档案的相对位置,该相对位置是相对于包含xml-stylesheet 处理指令的XML 文件的所在目录,如下所示:
<?xml-stylesheet type="text/xsl" href="Inventory.xsl"?>
    (因为一般会将XSL 样式表储存在与XML 文件相同的目录或子目录中,因此相对的URL 较常被使用。)
    提示
    虽然你可以使用完整的URL 来连结XSL 样式表,但该样式表必须与相连结的XML 文件储存于相同的domain。例如,如果 http://mspress.microsoft.com/ 的domain 中包含了一个XML 文件,则要连结的XSL 样式表也必须在相同的domain 中。
    通常你会将xml-stylesheet 处理指令加到文件的序文中,位在XML 宣告后面,你可以在下节列表10-2 中的范例XML 文件看到相关范例。
    想要了解更多有关处理指令与任何合法放置处理指令位置的叙述,请参阅第四章 <使用处理指令> 的部分。
    如果你已经将XSL 样式表与XML 文件连结在一起,你可以在Internet Explorer 5 中直接开启此XML 文件,浏览器会利用样式表中的转换指令来显示XML 文件。不像串接样式表,如果你将多个XSL 样式表连结至XML 文件时,浏览器将使用第一个XSL 样式表,而忽略其它样式表。如果你同时将串接样式表与XSL 样式表链接至同一份XML 文件,浏览器将只会使用XSL 样式表。
    注意
    如果XML 文件并没有连结串接样式表或XSL 样式表,则Internet Explorer 5 将使用预设的内建XSL 样式表来显示此XML 文件。这个内建的样式表会以可延展/收缩的树状结构来显示XML的资源,如同第二章中<显示不含样式表的XML 文件>中所介绍的一样。

使用单一的XSL 样板

    不像在串接样式表中包含的是规则(rules),XSL 样式表包含了一个或多个样板,每个样板包含了XML 文件中特定分枝的元素的展示信息。在本节中,你将会学习如何建立一个只包含单一样板的简单XSL 样式表。这个样板包含了显示整份文件的信息。
    列表10-1 提供了第一个XSL 样式表范例。该样式表被链接到列表10-2 中的XML 文件。(你可以在随书光盘的 XslDemo01.xsl 和 XslDemo01.xml 档案中找到。)
XslDemo01.xsl
<?xml version="1.0"?>
<!--File Name:XslDemo01.xsl -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
<xsl:template match="/">
<H2>Book Description</H2>
<SPAN STYLE="font-style:italic">Author:</SPAN>
<xsl:value-of select="BOOK/AUTHOR"/><BR/>
<SPAN STYLE="font-style:italic">Title:</SPAN>
<xsl:value-of select="BOOK/TITLE"/><BR/>
<SPAN STYLE="font-style:italic">Price:</SPAN>
<xsl:value-of select="BOOK/PRICE"/><BR/>
<SPAN STYLE="font-style:italic">Binding type:</SPAN>
<xsl:value-of select="BOOK/BINDING"/><BR/>
<SPAN STYLE="font-style:italic">Number of pages:</SPAN>
<xsl:value-of select="BOOK/PAGES"/>
</xsl:template>
</xsl:stylesheet>

XslDemo01.xml
<?xml version="1.0"?>
<!--File Name:XslDemo01.xml -->
<?xml-stylesheet type="text/xsl" href="XslDemo01.xsl"?>
<BOOK>
<TITLE>Moby-Dick</TITLE>
<AUTHOR>
<FIRSTNAME>Herman</FIRSTNAME>
<LASTNAME>Melville</LASTNAME>
</AUTHOR>
<BINDING>hardcover</BINDING>
<PAGES>724</PAGES>
<PRICE>$9.95</PRICE>
</BOOK>
    下图为Internet Explorer 5 使用XSL 样式表来显示XML 文件的情形:

     每一个XSL 样式表必须拥有下页所显示的文件元素。(回想一下文件元素,也称为根元素,是在XML 元素结构中包含了文件中所其它元素的顶层元素。)
<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
<!--one or more template elements...-->
</xsl:stylesheet>
    文件元素xsl:stylesheet 的工作不仅是包含文件中其它元素,也负责识别此文件为XSL 样式表。这个元素是样式表中使用的特定目的元素之一。
    所有的XSL 元素都属于xsl 命名空间-即,将「xsl:」命名空间设定放在每个XSL 元素的名字之前作为起始字符串,随后才接着元素自己本身的名称。你可以在xsl:stylesheet 元素的起始卷标中定义这个命名空间,如下所示:
xmlns:xsl="http://www.w3.org/TR/WD-xsl"
    这个定义让你可以在任何样式表的元素中使用此命名空间。关于XML 命名空间的一般介绍,请参阅第七章 <将HTML 元素加到XML 文件并使用命名空间> 的内容。
    XSL 样式表中的xsl:stylesheet 文件元素,必须包含一个以上的XSL 样板元素,简称为样板。列表10-1 中的文件元素,只包含单一个样板,其格式如下所示:
<xsl:template match="/">
<!--child elements...-->
</xsl:template>
    浏览器使用样板来显示样式表所连结的XML 文件,其元素阶层结构中的特定分枝。样板的match属性用来指出特定的分枝。(match 属性与串接样式表的选择器很类似。)match 属性的属性值被称为样本(pattern)。在此范例中,样本是以「/」或「matches」来代表整个XML 文件的根元素。因此这个特定样板包含了显示整个XML 文件的指令。
    每个XSL 样式表中必须精确地只包含一个match 属性被设定为「/」的样板。如同你在本章稍后将学习的,你也可以含括一个以上的额外样板,样板内含负责显示XML 文件的元素结构中特定分枝的指令;每个样板必须有对应到特定分枝的样本。
    了解根样本(/)并不表示代表整个XML 文件的文件元素(或根元素)是非常重要的。更确切的说,根样本代表了整个文件,文件元素只是文件中的一个子元素。(因此根样本与第九章中讨论的文件对象模型(DOM)的Document 节点是非常相似的。)
    下面是范例样式表的完整范例:
<xsl:template match="/">
<H2>Book Description</H2>
<SPAN STYLE="font-style:italic">Author:</SPAN>
<xsl:value-of select="BOOK/AUTHOR"/><BR/>
<SPAN STYLE="font-style:italic">Title:</SPAN>
<xsl:value-of select="BOOK/TITLE"/><BR/>
<SPAN STYLE="font-style:italic">Price:</SPAN>
<xsl:value-of select="BOOK/PRICE"/><BR/>
<SPAN STYLE="font-style:italic">Binding type:</SPAN>
<xsl:value-of select="BOOK/BINDING"/><BR/>
<SPAN STYLE="font-style:italic">Number of pages:</SPAN>
<xsl:value-of select="BOOK/PAGES"/>
</xsl:template>
    代表 HTML 卷标的 XML 元素 。下面是这类XML 元素置于样式表前端的范例:
<H2>Book Description</H2>
    是以第二级的字型来显示标题的程序代码,
<SPAN STYLE="font-style:italic">Author:</SPAN>
    上面程序代码则将以斜体字型显示文字区块Author,而
<BR/>
    则是一个换行指令。
    这些都是格式正确的XML 元素,用来代表标准的HTML 元素。浏览器只是简单地将每个HTML 元素直接复制到浏览器所处理且显示的HTML 输出中。
    提示
    每个代表HTML 卷标的元素,必须是格式正确的XML 元素,且也是标准的HTML元素。(不要忘记XSL 样式表也是一个XML 文件。)因此,你不能使用格式不正确的XML 元素来建立HTML 元素,像是只有起始卷标的元素。例如,要指定一个中断元素,你不能像你在HTML 网页中简单输入<BR>。更确切的说,你必须使用格式正确的XML 空白元素卷标<BR/>,来指定一个中断元素。
    XSL 元素 。置于形态样式表前端的XSL 元素是xsl:value-of 元素,如下所示:
<xsl:value-of select="BOOK/AUTHOR"/>
    因为使用「xsl:」命名空间设定,浏览器能将XML 元素从代表HTML 的元素区别出来。位于样板中的XSL 元素便不会被复制到HTML 的输出上。更确切地说,XSL 元素包含了用来选择和修改XML 数据,或执行其它工作的指令。
    XSL 元素value-of 会将特定XML 元素的文字内容-包含任何该XML 元素所拥有的子元素的文字内容-加到浏览器处理和显示的HTML 输出中。你可以藉由将样本指定到value-of XSL 元素的select 属性,来指定特定的XML 元素。在先前范例中的value-of 元素,其select 属性被设定为「BOOK/AUTHOR」,会使得value-of 元素将XML 文件中AUTHOR 元素的文字内容加到HMTL 的输出结果中。AUTHOR 元素的文字内容是由两个子元素FIRSTNAME 和LASTNAME中的字符数据所组成。
    注意,在样本中,你可以藉者使用路径运算子(path operator)(此范例中为BOOK/AUTHOR)来指定XML 元素,路径运算子指出此XML 元素在XML 文件元素阶层结构中的位置。(路径运算子与操作系统中的档案路径相似,档案路径是用来指定档案或目录的所在位置)。
    在此必须了解的重要观念是,select 属性值中的路径运算子是相对于目前元素位置的相对位置。在XSL 样式表中每个元素拥有一个目前元素。因为范例的样板对应到整个文件的根元素(透过属性设定match "/"),所以在样板值中的目前元素是文件的根元素。(在这个范例中,目前元素不是字义上的元素,而是文件元素的根。)因此,在样板中,路径运算子BOOK/AUTHOR 指出元素AUTHOR 是位在BOOK 元素中,且位在文件的根中。(因此在select 属性值中的路径运算子与部分的档案路径非常相似,该路径是指出该档案相对于目前工作目录的相对位置。)=如果你省略了XSL 元素value-of 的select 属性设定,元素value-of 会输出目前元素及其所有子元素的文字内容。(在此范例中,因为目前元素是整个文件的根元素,所以省略select 属性的设定,将输出XML 文件中所有的字符数据。)范例样板中元素的整个结果是将XML 文件中每个子元素的文字卷标(例如AUTHOR、TITLE、PRICE、BINDING 和PAGES),及每个子元素的文字内容显示出来。注意,这些value-of 元素在样板中的顺序将决定浏览器显示这些元素的顺序。因此,即使是在这个简单的样式表中,你已经可以看到XSL 样式表的确要比串接样式表来得更有弹性,因为串接样式表只能以元素在文件中的顺序来显示。
    概要而言,你可以看到XSL 样式表选择性地将XML 元素转换成HTML 卷标区块,来告诉浏览器如何显示一份XML 文件,而浏览器就像处理HTML 网页中的标签一样,只需依HTML 标签区块来处理及显示即可。然而,要注意的是,在XSL 样板中你不能包含代表HTML 网页中标准的元素(如HTML 和BODY),因为浏览器实际上会为你插入相对应的HTML 标签区块。
    下图显示了浏览器如何产生列表10-1 和10-2 中的范例文件及样式表与相对应的HTML 标签区块的起始部分。

提示
    在微软提供的网页 http://msdn.microsoft.com/workshop/author/default.asp 中,可获得InternetExplorer 5 处理HTML 和Dynamic HTML 的相关信息。在W3C 提供的网页 http://www.w3.org/TR/REC-html40/ 中,可取得HTML 的官方规格文件。

显示多个元素

    上节列表10-2 所提供的XML 文件范例中,只包含了一个BOOK 元素。然而,当文件中包含了数个BOOK 元素时,先前你所学到的技术只能显示第一个BOOK 元素。例如,一份XML 文件内含下列的文件元素:
<INVENTORY>
<BOOK>
<TITLE>The Adventures of Huckleberry Finn</TITLE>
<AUTHOR>
<FIRSTNAME>Mark</FIRSTNAME>
<LASTNAME>Twain</LASTNAME>
</AUTHOR>
<BINDING>mass market paperback</BINDING>
<PAGES>298</PAGES>
<PRICE>$5.49</PRICE>
</BOOK>
<BOOK>
<TITLE>The Adventures of Tom Sawyer</TITLE>
<AUTHOR>
<FIRSTNAME>Mark</FIRSTNAME>
<LASTNAME>Twain</LASTNAME>
</AUTHOR>
<BINDING>mass market paperback</BINDING>
<PAGES>205</PAGES>
<PRICE>$4.75</PRICE>
</BOOK>
<BOOK>
<TITLE>The Ambassadors</TITLE>
<AUTHOR>
<FIRSTNAME>Henry</FIRSTNAME>
<LASTNAME>James</LASTNAME>
</AUTHOR>
<BINDING>mass market paperback</BINDING>
<PAGES>305</PAGES>
<PRICE>$5.95</PRICE>
</BOOK>
</INVENTORY>
    假设被用来显示文件的样式表包含下面所列的样板:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
<xsl:template match="/">
<H2>Book Description</H2>
<SPAN STYLE="font-style:italic">Author:</SPAN>
<xsl:value-of select="INVENTORY/BOOK/AUTHOR"/><BR/>
<SPAN STYLE="font-style:italic">Title:</SPAN>
<xsl:value-of select="INVENTORY/BOOK/TITLE"/><BR/>
<SPAN STYLE="font-style:italic">Price:</SPAN>
<xsl:value-of select="INVENTORY/BOOK/PRICE"/><BR/>
<SPAN STYLE="font-style:italic">Binding type:</SPAN>
<xsl:value-of select="INVENTORY/BOOK/BINDING"/><BR/>
<SPAN STYLE="font-style:italic">Number of pages:</SPAN>
<xsl:value-of select="INVENTORY/BOOK/PAGES"/>
</xsl:template>
</xsl:stylesheet>
    这个样板使用到先前讨论过的技术。注意,指定给select 属性的样本是以文件元素作为起始,在此范例是INVENTORY (例如,「INVENTORY/BOOK/AUTHOR」)。
    然而,每个样本对应三个不同的元素。例如,「INVENTORY/BOOK/AUTHOR」对应三个BOOK元素中的AUTHOR 元素。在此情形,浏览器将只使用第一个对应的BOOK 元素中的AUTHOR元素。因此样式表将只显示第一个BOOK 元素的内容,如下图所示:

    一种显示所有对应元素的方法是使用XSL 元素for-each 来达成,该元素重复输出相对应的元素,直到XML 档案中所有的对应元素皆被处理过。显示于列表10-3 的XSL 样式表中示范了这项技术。这份样式表被连结到列表10-4 中的XML 文件。(你可以在随书光盘
的 XslDemo02.xsl 和 XslDemo.xml 档案中找到列表10-3 和10-4。)
XslDemo02.xsl
<?xml version="1.0"?>
<!--File Name:XslDemo02.xsl-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
<xsl:template match="/">
<H2>Book Inventory</H2>
<xsl:for-each select="INVENTORY/BOOK">
<SPAN STYLE="font-style:italic">Title:</SPAN>
<xsl:value-of select="TITLE"/><BR/>
<SPAN STYLE="font-style:italic">Author:</SPAN>
<xsl:value-of select="AUTHOR"/><BR/>
<SPAN STYLE="font-style:italic">Binding
type:</SPAN>
<xsl:value-of select="BINDING"/><BR/>
<SPAN STYLE="font-style:italic">Number of
pages:</SPAN>
<xsl:value-of select="PAGES"/><BR/>
<SPAN STYLE="font-style:italic">Price:</SPAN>
<xsl:value-of select="PRICE"/><P/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

XslDemo.xml
<?xml version="1.0"?>
<!--File Name:XslDemo.xml-->
<?xml-stylesheet type="text/xsl" href="XslDemo02.xsl"?>
<INVENTORY>
<BOOK>
<TITLE>The Adventures of Huckleberry Finn</TITLE>
<AUTHOR>
<FIRSTNAME>Mark</FIRSTNAME>
<LASTNAME>Twain</LASTNAME>
</AUTHOR>
<BINDING>mass market paperback</BINDING>
<PAGES>298</PAGES>
<PRICE>$5.49</PRICE>
</BOOK>
<BOOK>
<TITLE>The Adventures of Tom Sawyer</TITLE>
<AUTHOR>
<FIRSTNAME>Mark</FIRSTNAME>
<LASTNAME>Twain</LASTNAME>
</AUTHOR>
<BINDING>mass market paperback</BINDING>
<PAGES>205</PAGES>
<PRICE>$4.75</PRICE>
</BOOK>
<BOOK>
<TITLE>The Ambassadors</TITLE>
<AUTHOR>
<FIRSTNAME>Henry</FIRSTNAME>
<LASTNAME>James</LASTNAME>
</AUTHOR>
<BINDING>mass market paperback</BINDING>
<PAGES>305</PAGES>
<PRICE>$5.95</PRICE>
</BOOK>
<BOOK>
<TITLE>The Awakening</TITLE>
<AUTHOR>
<FIRSTNAME>Kate</FIRSTNAME>
<LASTNAME>Chopin</LASTNAME>
</AUTHOR>
<BINDING>mass market paperback</BINDING>
<PAGES>195</PAGES>
<PRICE>$4.95</PRICE>
</BOOK>
<BOOK>
<TITLE>Billy Budd</TITLE>
<AUTHOR>
<FIRSTNAME>Herman</FIRSTNAME>
<LASTNAME>Melville</LASTNAME>
</AUTHOR>
<BINDING>mass market paperback</BINDING>
<PAGES>195</PAGES>
<PRICE>$4.49</PRICE>
</BOOK>
<BOOK>
<TITLE>A Connecticut Yankee in King Arthur 's
Court</TITLE>
<AUTHOR>
<FIRSTNAME>Mark</FIRSTNAME>
<LASTNAME>Twain</LASTNAME>
</AUTHOR>
<BINDING>mass market paperback</BINDING>
<PAGES>385</PAGES>
<PRICE>$5.49</PRICE>
</BOOK>
<BOOK>
<TITLE>Joan of Arc</TITLE>
<AUTHOR>
<FIRSTNAME>Mark</FIRSTNAME>
<LASTNAME>Twain</LASTNAME>
</AUTHOR>
<BINDING>trade paperback</BINDING>
<PAGES>465</PAGES>
<PRICE>$6.95</PRICE>
</BOOK>
<BOOK>
<TITLE>Leaves of Grass</TITLE>
<AUTHOR>
<FIRSTNAME>Walt</FIRSTNAME>
<LASTNAME>Whitman</LASTNAME>
</AUTHOR>
<BINDING>hardcover</BINDING>
<PAGES>462</PAGES>
<PRICE>$7.75</PRICE>
</BOOK>
<BOOK>
<TITLE>The Legend of Sleepy Hollow</TITLE>
<AUTHOR>
<FIRSTNAME>Washington</FIRSTNAME>
<LASTNAME>Irving</LASTNAME>
</AUTHOR>
<BINDING>mass market paperback</BINDING>
<PAGES>98</PAGES>
<PRICE>$2.95</PRICE>
</BOOK>
<BOOK>
<TITLE>The Marble Faun</TITLE>
<AUTHOR>
<FIRSTNAME>Nathaniel</FIRSTNAME>
<LASTNAME>Hawthorne</LASTNAME>
</AUTHOR>
<BINDING>trade paperback</BINDING>
<PAGES>473</PAGES>
<PRICE>$10.95</PRICE>
</BOOK>
<BOOK>
<TITLE>Moby-Dick</TITLE>
<AUTHOR>
<FIRSTNAME>Herman</FIRSTNAME>
<LASTNAME>Melville</LASTNAME>
</AUTHOR>
<BINDING>hardcover</BINDING>
<PAGES>724</PAGES>
<PRICE>$9.95</PRICE>
</BOOK>
<BOOK>
<TITLE>Passing</TITLE>
<AUTHOR>
<FIRSTNAME>Nella</FIRSTNAME>
<LASTNAME>Larsen</LASTNAME>
</AUTHOR>
<BINDING>trade paperback</BINDING>
<PAGES>165</PAGES>
<PRICE>$5.95</PRICE>
</BOOK>
<BOOK>
<TITLE>The Portrait of a Lady</TITLE>
<AUTHOR>
<FIRSTNAME>Henry</FIRSTNAME>
<LASTNAME>James</LASTNAME>
</AUTHOR>
<BINDING>mass market paperback</BINDING>
<PAGES>256</PAGES>
<PRICE>$4.95</PRICE>
</BOOK>
<BOOK>
<TITLE>Roughing It</TITLE>
<AUTHOR>
<FIRSTNAME>Mark</FIRSTNAME>
<LASTNAME>Twain</LASTNAME>
</AUTHOR>
<BINDING>mass market paperback</BINDING>
<PAGES>324</PAGES>
<PRICE>$5.25</PRICE>
</BOOK>
<BOOK>
<TITLE>The Scarlet Letter</TITLE>
<AUTHOR>
<FIRSTNAME>Nathaniel</FIRSTNAME>
<LASTNAME>Hawthorne</LASTNAME>
</AUTHOR>
<BINDING>trade paperback</BINDING>
<PAGES>253</PAGES>
<PRICE>$4.25</PRICE>
</BOOK>
<BOOK>
<TITLE>The Turn of the Screw</TITLE>
<AUTHOR>
<FIRSTNAME>Henry</FIRSTNAME>
<LASTNAME>James</LASTNAME>
</AUTHOR>
<BINDING>trade paperback</BINDING>
<PAGES>384</PAGES>
<PRICE>$3.35</PRICE>
</BOOK>
</INVENTORY>
    列表10-3 的样式表中的样板,包含下列的元素for-each:
<xsl:for-each select="INVENTORY/BOOK">
<SPAN STYLE="font-style:italic">Title:</SPAN>
<xsl:value-of select="TITLE"/><BR />
<SPAN STYLE="font-style:italic">Author:</SPAN>
<xsl:value-of select="AUTHOR"/><BR/>
<SPAN STYLE="font-style:italic">Binding type:</SPAN>
<xsl:value-of select="BINDING"/><BR/>
<SPAN STYLE="font-style:italic">Number of pages:</SPAN>
<xsl:value-of select="PAGES"/><BR/>
<SPAN STYLE="font-style:italic">Price:</SPAN>
<xsl:value-of select="PRICE"/><P/>
</xsl:for-each>
    for-each 元素有两个主要的作用:
    元素for-each 从其select 属性中指定的样本相对应XML 文件元素集合中,每次输出此集合中相对应XML 元素的元素区块,直到集合中的元素都输出完成。在此范例中,循环重复输出在INVENTORY 文件元素中找到的BOOK 元素。for-each元素的select 属性中指定的样本与先前描述过的value-of 元素的select 属性中指定的样本其运作模式是一样的。
    在for-each 元素中,目前元素是由for-each 元素的select 属性来设定(在此范例中,/INVENTORY/BOOK 是指在文件根元素下的子元素INVENTORY 下所有的BOOK 元素。),如下所示:
<xsl:stylesheetxmlns:xsl="http://www.w3.org/TR/WD-xsl">
<xsl:template match="/">
<!--Here,the current"element" is the document root,"/".-->
<xsl:for-each select="INVENTORY/BOOK">
<!--Here,the current element is /INVENTORY/BOOK.-->
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
    因此,在for-each 元素中,每个BOOK 元素的子元素,只是简单地在样本中加入子元素名称,如下列程序代码所示:
<xsl:value-of select="TITLE"/>
    最后的输出,包含此XML 文件中所有BOOK 元素的数据,而不用考虑到底文件中包含了多少个BOOK 元素。下图为在Internet Explorer 5 中显示前面三笔BOOK 元素信息的画面。(将滚动条向下移动,将显示剩余的元素信息。)


使用多重样板

    显示重复的XML 元素的另一方法,是为此元素建立一个个别的样板,然后使用XSL 元素apply-templates 来启动此样板。列表10-5 的范例XSL 样式表使用了这种方法。(你可以在随书光盘的XslDemo03.xsl 档案中找到这个样式表。)这个样式表是设计来与列表10-4 中的XML文件(XslDemo.xml)相连结;因此你必须将文件中的xml-stylesheet 指令修改成如下,来把样式表联结至列表10-5 中的XML 文件:
<?xml-stylesheet type="text/xsl" href="XslDemo03.xsl"?>
XslDemo03.xsl
<?xml version="1.0"?>
<!--File Name:XslDemo03.xsl -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
<xsl:template match="/">
<H2>Book Inventory</H2>
<xsl:apply-templates select="INVENTORY/BOOK" //>
</xsl:template>
<xsl:template match="BOOK">
<SPAN STYLE="font-style:italic">Title:</SPAN>
<xsl:value-of select="TITLE"/><BR/>
<SPAN STYLE="font-style:italic">Author:</SPAN>
<xsl:value-of select="AUTHOR"/><BR/>
<SPAN STYLE="font-style:italic">Binding type:</SPAN>
<xsl:value-of select="BINDING"/><BR/>
<SPAN STYLE="font-style:italic">Number of pages:</SPAN>
<xsl:value-of select="PAGES"/><BR/>
<SPAN STYLE="font-style:italic">Price:</SPAN>
<xsl:value-of select="PRICE"/><P/>
</xsl:template>
</xsl:stylesheet>
    这个范例样式表中拥有两个样板。一个包含显示整份文件的指令。(透过match="/"的设定,来指定文件根元素)所有的XSL 样式表都必须具有这个样板。另一个样板则包含了显示BOOK 元素的指令。(这个样板中的match= "BOOK"的设定)浏览器会先从处理对应到文件根元素的样板:
<xsl:template match="/">
<H2>Book Inventory</H2>
<xsl:apply-templates select="INVENTORY/BOOK"//>
</xsl:template>
    XSL 元素apply-templates 告诉浏览器对于根元素INVENTORY 中的每个BOOK 元素,浏览器必须处理每个对应到BOOK 元素的样板-即match 属性被设定成「BOOK」的样板。样式表中包含了下列对应到BOOK 元素的样板:
<xsl:template match="BOOK">
<SPAN STYLE="font-style:italic">Title:</SPAN>
<xsl:value-of select="TITLE"/><BR/>
<SPAN STYLE="font-style:italic">Author:</SPAN>
<xsl:value-of select="AUTHOR"/><BR/>
<SPAN STYLE="font-style:italic">Binding type:</SPAN>
<xsl:value-of select="BINDING"/><BR/>
<SPAN STYLE="font-style:italic">Number of pages:</SPAN>
<xsl:value-of select="PAGES"/><BR/>
<SPAN STYLE="font-style:italic">Price:</SPAN>
<xsl:value-of select="PRICE"/><P/>
</xsl:template>
    因为样板对应到BOOK 元素,而BOOK 元素正是样板中上下文内的目前元素。因此每个BOOK元素的子元素,只是如下所示简单地将元素名称加入至样本中来进行存取:
<xsl:value-of select="TITLE"/>
注意
    如果元素apply-templates 中的select 属性设定省略时,浏览器会处理对应到目前元素中每个子元素的样板(如果有的话)。在这个范例中,apply-templates 元素,即目前元素(文件根元素),只有一个子元素INVENTORY,而INVENTORY 没有相对应的样板。因此,如果你将select 属性的设定省略,将不会有任何输出发生。
    浏览器会处理每个对应BOOK 元素的样板,藉以显示文件中所有书籍的信息: