使用 XSLT 2.0 为内容添加结构和语义
将非结构化的叙述性内容转换为结构化的、具有丰富特性的 XML
过去,叙述性内容进行了标记,用于表示内容的外观(例如,字体大小或文本对齐方式),而不是其真实的结构或含义。这种方法非常适用于图书印刷、办公文档以及许多 Web 页面的内容。一些叙述性内容根本没有进行标记,而是以纯文本段落形式呈现。
随着内容管理、电子发布、高级搜索和查询技术的出现,内容所有者现在已认识到结构化信息的威力,并使用相应的方式来标记他们的新内容。但是,许多人仍然存留有旧的内容,这些内容是非结构化或半结构化的,或只为了演示目的而进行标记。
为了令现有内容更具可读性,可为其添加结构,从而使您能够:
- 分别对多个输出设备(如智能手机、电子书阅读器和替代 Web 浏览器)的内容进行样式化
- 实现与某些种类的文本(比如文档内部或文档之间的引用中的超链接,或用于地址的弹出指示)有关的交互式行为
- 生成内容的替代表示,如内容表、索引和摘要视图
- 根据内容中的字段提供更受专注的搜索
- 确保整个内容正文具有更一致的格式
- 改进对内容的检验,例如,确定某个法律文档中的文档内部引用是否有效
使用 XSLT 2.0
XSLT 2.0 是一种适应性很强的技术,可用于为叙述性内容添加结构。人们越来越多地使用 XML 或易于转化为 XML 的格式(如 HTML)来表示叙述性内容。与其他一些用于处理文本的流行脚本语言不同的是,XSLT 完全支持 XML。它理解 XML 语法、编码和名称空间的许多变体。
XSLT 同样适用于叙述性内容,因为它提供了很好的灵活性。使用模板规则处理输入文档中的各种事件意味着会话可以是由内容驱动的,而不是严格按照顺序控制。
与专注于 XML 样式化的 XSLT 1.0 不同,XSLT 2.0 提供了一些用于转换内容的高级功能,这些功能可以实现以下操作:
- 通过正则表达式来确定文本中的模式
- 按照值或位置对元素进行分组
- 一个样式表一个文档地多次传递文档
- 将一个文档分割成多个文档,或将多个文档组合成一个文档
要使用 XSLT,第一步是将内容转换为 XML 形式。大多数文档编辑器和其他内容工具都有 XML 导出功能。根据所使用的工具,XML 很可能非常复杂,因此第一步是将 XML 转换为一种简便形式,以便更容易处理它。
如果是从 HTML 进行转换,HTML Tidy(参见 参考资料 中的链接)会将您的 HTML 转换为 XHTML,可以将 XHTML 作为 XSLT 的输入,因为它是一种格式良好的 XML。它还简化了您的文档。
技巧
本文其余部分将介绍使用 XSLT 2.0 为内容添加结构和语义的技巧,并且特别关注作为输入文档的 XHTML 和 Microsoft® Office Word XML,但这些概念适用于任何叙述性输入文档。
您可以在本节中以可下载的 ZIP 文件(参见 下载)的形式下载所有示例。对于 XSLT 2.0 处理,我建议使用 Saxon(参见 参考资料 中的链接)。
识别文本模式
识别文本中的特定模式并进行标记通常十分有用。URL、电子邮件地址、电话号码、文档间引用以及 wiki 类型的格式化都遵循通用的模式,可以通过正则表达式识别它们。
清单 1 显示了一个输入文档,该文档包含纯文本形式的电子邮件地址。假设您希望使用 a
(锚)元素标记每个电子邮件地址,从而实现电子邮件地址的链接,该链接采用 HTML 表示,允许用户通过单击地址来向其发送电子邮件。
清单 1. 文本模式识别 XSLT 的样例输入
<document> <p>Priscilla Walmsley can be reached at pwalmsley@datypic.com.</p> <p>Questions about XSLT in general are best asked on the XSL list at xsl-list@lists.mulberrytech.com (subscription required.) </p> </document>
清单 2 中的 XSLT 实现了这个目标。它使用 XSLT 2.0 analyze-string
指令对字符串进行测试,看它是否与某个正则表达式匹配。analyze-string
指令有两个子元素:matching-substring
表示如何处理匹配模式的子字符串,而 non-matching-substring
则表示如何处理其余的文本。
在本例中,第一个模板规则匹配输入文档中的每个文本节点。当它发现匹配 regex
属性中指定的正则表达式的文本后,它将插入一个
a
元素。该元素提供了一个 href
属性,将字符串 mailto:
与电子邮件地址连接起来。它还将电子邮件地址放入 a
元素的内容中。在 matching-substring
指令内部,句号(.
)表示匹配模式的字符串。
如果全部或部分文本节点与模式不匹配,则仅执行复制操作,如 non-matching-substring
中定义的那样。XSLT 中的第二个模板规则会命令处理器复制所有元素并继续执行子元素,因此,除了电子邮件地址外,其他内容没有发生改变。
清单 2. 文本模式识别 XSLT
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="text()"> <xsl:analyze-string select="." regex="[A-Za-z0-9._%-]+@[A-Za-z0-9.-]+\.[A-Za-z]{{2,4}}"> <xsl:matching-substring> <a href="mailto:{.}"> <xsl:value-of select="."/> </a> </xsl:matching-substring> <xsl:non-matching-substring> <xsl:copy/> </xsl:non-matching-substring> </xsl:analyze-string> </xsl:template> <xsl:template match="*"> <xsl:copy> <xsl:copy-of select="@*"/> <xsl:apply-templates/> </xsl:copy> </xsl:template> </xsl:stylesheet>
清单 3 显示 XSLT 的输出,其中电子邮件地址标记为 a
元素。
清单 3. 文本模式识别 XSLT 的样例输出
<document> <p>Priscilla Walmsley can be reached at <a href="mailto:pwalmsley@datypic.com">pwalmsley@datypic.com</a>.</p> <p>Questions about XSLT in general are best asked on the XSL list at <a href="mailto:xsl-list@lists.mulberrytech.com">xsl-list@lists.mulberrytech.com</a> (subscription required.) </p> </document>
添加结构容器
在较高的层面上,添加表示文档分支或小节的结构通常很有用。您可以添加结构以遵循某种特定的 XML 词汇表,比如 DocBook。或者您可能希望清晰地描述部分内容,从而可以使用 DITA 之类的技术重新构建内容。
例如,清单 4 展示了一个采用扁平结构的 XHTML 输入文档。小节标题(h1
和 h2
)出现在与段落相同的级别,并且未使用结构标记对小节进行分组。
清单 4. 节分组 XSLT 的样例输入
<html> <h1>Chapter 1</h1> <h2>Section 1.1</h2> <p>In this section...</p> <p>More text</p> <h2>Section 1.2</h2> <p>In this second section...</p> </html>
清单 5 中的 XSLT 使用 XSLT 2.0 的分组功能根据小节标题的位置添加 section
元素。它创建了两个级别的组。首先,它使用一个 for-each-group
指令,该指令使用 group-starting-with="h1"
属性对 html
的所有子元素进行分组。该方法意味着 h1
元素表示某个组在这个级别的开始部分。XSLT 会为这些组中的每一个组插入一个 section level="1"
元素。
其次,它包含一个内部 for-each-group
,后者调用 current-group
函数获取 h1
组中的所有项,并使用它们创建子组。子组的开始部分由 h2
元素定义。
在内部 for-each-group
中,它将使用 XPath
current-group()[self::h2]
测试组是否包含 h2
元素。这样做是因为要创建一个组,其中的所有内容均位于第一个 h2
元素之前,在本例中,该元素是
h1
元素。您可能并不希望其他 section level="2"
围绕该元素。
清单 5. 对 XSLT 中的节进行分组
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="html"> <document> <xsl:for-each-group select="*" group-starting-with="h1"> <section level="1"> <xsl:for-each-group select="current-group()" group-starting-with="h2"> <xsl:choose> <xsl:when test="current-group()[self::h2]"> <section level="2"> <xsl:apply-templates select="current-group()"/> </section> </xsl:when> <xsl:otherwise> <xsl:apply-templates select="current-group()"/> </xsl:otherwise> </xsl:choose> </xsl:for-each-group> </section> </xsl:for-each-group> </document> </xsl:template> <xsl:template match="h1|h2"> <heading> <xsl:apply-templates/> </heading> </xsl:template> <xsl:template match="node()"> <xsl:copy> <xsl:copy-of select="@*"/> <xsl:apply-templates/> </xsl:copy> </xsl:template> </xsl:stylesheet>
清单 6 展示了 XSLT 的输出,其中包含两级 section
元素。
清单 6. 节分组 XSLT 的样例输出
<document> <section level="1"> <heading>Chapter 1</heading> <section level="2"> <heading>Section 1.1</heading> <p>In this section...</p> <p>More text</p> </section> <section level="2"> <heading>Section 1.2</heading> <p>In this second section...</p> </section> </section> </document>
分组不是基于起始元素,相反,有时需要对彼此相邻的项进行分组。列表项就是这样一个例子,其表现形式就是一些相邻的普通段落,而非列表中分组到一起的内容。因此,for-each-group
指令可以使用
group-adjacent
属性代替
group-starting-with
。
从节号推测结构
有时,您希望同时进行分组并推测结构。与之前的示例不同,清单 7 中的输入文档的所有文本都被标记为通用段落。辨别结构的唯一方法是对内容进行测试以获得相应模式。
清单 7. 节推测 XSLT 的样例输入
<document> <p>Chapter 1: In the beginning</p> <p>In this chapter...</p> <p>1.1 Introduction</p> <p>In this section...</p> <p>More text</p> <p>1.2 Next Steps</p> <p>In this second section...</p> </document>
实现这一目标的最简便方法就是使用 XSLT。清单 8 中的 XSLT 对文档遍历了两次,并使用模式区分这两次遍历功能。
清单 8. 节推测 XSLT
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:variable name="chapRegex" select="'^\s*Chapter\s+(\d+)\s*:\s*(.*)$'"/> <xsl:variable name="secRegex" select="'^\s*(\d+\.\d+)\s*(.*)$'"/> <xsl:template match="document"> <xsl:variable name="renamed" as="element()*"> <xsl:apply-templates select="*" mode="rename"/> </xsl:variable> <document> <xsl:for-each-group select="$renamed" group-starting-with="chapTitle"> <chapter num="{replace(current-group()[self::chapTitle],$chapRegex,'$1')}"> <xsl:for-each-group select="current-group()" group-starting-with="secTitle"> <xsl:choose> <xsl:when test="current-group()[self::secTitle]"> <section num="{replace(current-group()[self::secTitle],$secRegex,'$1')}"> <xsl:apply-templates select="current-group()"/> </section> </xsl:when> <xsl:otherwise> <xsl:apply-templates select="current-group()"/> </xsl:otherwise> </xsl:choose> </xsl:for-each-group> </chapter> </xsl:for-each-group> </document> </xsl:template> <xsl:template match="p[matches(.,$chapRegex)]" mode="rename"> <chapTitle> <xsl:copy-of select="node()"/> </chapTitle> </xsl:template> <xsl:template match="p[matches(.,$secRegex)]" mode="rename"> <secTitle> <xsl:copy-of select="node()"/> </secTitle> </xsl:template> <xsl:template match="text()" priority="1"> <xsl:choose> <xsl:when test="matches(.,$chapRegex) and (. is parent::chapTitle/node()[1])"> <xsl:value-of select="replace(.,$chapRegex,'$2')"/> </xsl:when> <xsl:when test="matches(.,$secRegex) and (. is parent::secTitle/node()[1])"> <xsl:value-of select="replace(.,$secRegex,'$2')"/> </xsl:when> <xsl:otherwise> <xsl:copy-of select="."/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="node()" mode="#all"> <xsl:copy> <xsl:copy-of select="@*"/> <xsl:apply-templates mode="#current"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
第一次遍历将确定哪些 p
元素真正用于表示章标题和节标题,并对它们重新命名,以简化稍后进行的分组遍历。这里创建了一个 $renamed
变量,用来包含第一次遍历的结果。在其定义中,对模板应用了 rename
模式。rename
模式中的两个模板规则将查找表示章或节标题的段落,并重命名它们。为了确定这些段落,将使用 matches
函数(XSLT 2.0 中的新增内容),以确定某个字符串是否匹配正则表达式。在本例中,正则表达式使用变量 $chapRegex
和 $secRegex
表示。
清单 9 显示了第一次遍历后的 $renamed
变量,但是它没有直接显示在结果中。
清单 9. 节推测 XSLT 中的 $renamed 变量值
<document> <chapTitle>Chapter 1: In the beginning</chapTitle> <p>In this chapter...</p> <secTitle>1.1 Introduction</secTitle> <p>In this section...</p> <p>More text</p> <secTitle>1.2 Next Steps</secTitle> <p>In this second section...</p> </document>
第二次遍历以 for-each-group
指令开头,它的 select
属性表示它将处理 $renamed
变量而不是输入文档。第二次遍历使用与前一个例子十分类似的分组逻辑创建了一个两层结构:chapter
和 section
。
它还创建了包含章号和节号的 num
属性。为此,它使用了 XSLT 2.0 中的另一个新函数 replace
。replace
函数采用了三个参数:第一个参数是要修改的文本,第二个参数是与将要替换的部分匹配的正则表达式,第三个参数是替换字符串。在本例中,第三个参数利用了子表达式,其中 $2
表示它应当包括匹配正则表达式中第二个圆括号的文本。
text()
模板规则从内容中删除了章号和节号,因为可以将它们移至 num
属性。该属性也使用 replace
函数。您需要注意的是,不要通过替换每个与模式相匹配的文本节点来测试它是否是该父元素中的第一个文本节点。
node()
模板规则复制所有不具备更具体模板的元素。使用 mode="#all"
意味着不管您是应用 rename
模式还是没有应用任何模式,都将使用该模板。当按照该模板规则应用模板时,会使用 mode="#current"
表示您应当首先处于匹配模板的模式下。
尽管模式的使用在 XSLT 2.0 中并不新鲜,但是 #all
和 #current
关键字的应用是新出现的,同样,对文档执行多次遍历的功能也是新增的。由于结果树片段存在一些限制,所以这些功能无法在 XSLT 1.0 中实现。
清单 10 展示了最终输出。
清单 10. 节推测 XSLT 的样例输出
<document> <chapter num="1"> <chapTitle>In the beginning</chapTitle> <p>In this chapter...</p> <section num="1.1"> <secTitle>Introduction</secTitle> <p>In this section...</p> <p>More text</p> </section> <section num="1.2"> <secTitle>Next Steps</secTitle> <p>In this second section...</p> </section> </chapter> </document>
使用样式信息
指定样式对于判断文档的真正结构非常重要。尽管指定样式通常意味着指定格式并使其标准化,但也可以用它表示内容的结构和含义。在许多技术中,结构和样式是两种不同的事务。例如,在 Microsoft Office Word 中,文本被组织成段落,而样式则应用于这些段落或这些段落中的文本。在 HTML 中,结构化元素可能存在不同的变体,如 h1
和
p
,但是它们都将通过 class
属性来应用 “样式”,class
属性引用了 CSS 样式表。
图 1 展示了应用了样式的 Word 文档,其中标题 1 和标题 2 段落样式用于节标题,而 Emphasis 和 Strong 等字符样式应用于内部的文本格式。
图 1. 使用了样式的 Word 文档

在通过 XSLT 运行该文档之前,我将该文档保存为 Word XML。这里并没有提供 Word XML 文件,因为该文件体积庞大且十分复杂,但可以通过下载获得它(参见 下载)。
我建议创建一个样式映射文档,清单 11 显示了该文档的一个例子。它将输入文档中的样式映射到结果中的对应的结构元素。这种映射使转换变得更加通用和灵活,并且更加易于维护。
清单 11. Word 转换 XSLT 中的样式映射
<styles> <style> <name>BodyText</name> <name>Normal</name> <transformTo>p</transformTo> </style> <style> <name>ListParagraph</name> <transformTo>li</transformTo> </style> <style> <name>Heading1</name> <transformTo>h1</transformTo> </style> <style> <name>Heading2</name> <transformTo>h2</transformTo> </style> <style> <name>Emphasis</name> <transformTo>em</transformTo> </style> <style> <name>Strong</name> <transformTo>strong</transformTo> </style> </styles>
清单 12 中的 XSLT 将 Word
XML 文档转化为 XML,并创建了样式映射中指定的元素。它必须为以下两个元素定义模板规则:w:p
(段落)和 w:r
(文本运行)。对于这两个元素中的每一个,它都将确定相关的样式,并在样式映射中查找该样式。随后,它会使用 xsl:element
创建一个 XML 元素,其名称可以在样式映射的 transformTo
中找到。
清单 12. 将 Word 样式转化为 XML 标记
<?xml version="1.0"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" exclude-result-prefixes="w"> <xsl:variable name="styles" select="doc('stylemap.xml')/styles/style"/> <xsl:template match="/"> <document> <xsl:apply-templates select=".//w:p"/> </document> </xsl:template> <xsl:template match="w:p"> <xsl:variable name="elName" select="$styles[name=current()/w:pPr/w:pStyle/@w:val]/transformTo"/> <xsl:choose> <xsl:when test="$elName != ''"> <xsl:element name="{$elName}"> <xsl:apply-templates select="*"/> </xsl:element> </xsl:when> <xsl:otherwise> <!-- paragraphs without a listed style are just plain p's --> <p> <xsl:apply-templates select="*"/> </p> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="w:r"> <xsl:variable name="elName" select="$styles[name=current()/w:rPr/w:rStyle/@w:val]/transformTo"/> <xsl:choose> <xsl:when test="$elName != ''"> <xsl:element name="{$elName}"> <xsl:apply-templates select="*"/> </xsl:element> </xsl:when> <xsl:otherwise> <xsl:apply-templates select="*"/> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet>
清单 13 展示了样例输出。在本例中,我并没有实际添加或推测某些新的信息,而是将结构和样式组合到一组标记中。执行到这一步骤时,您可以应用本文所述的其他技巧来添加结构并识别文本模式。
清单 13. Word 样式转换 XSLT 的样例输出
<document> <h1>Chapter 1: In the beginning</h1> <p>In this chapter...</p> <h2>1.1 Introduction</h2> <p>In this section there is a list.</p> <li>item 1</li> <li>item 2</li> <li>item 3</li> <h2>1.2 Next Steps</h2> <p>This section uses character styles <strong>Strong</strong> and <em>Emphasis</em>.</p> </document>
尽管该示例使用的是 Word,但您也可以对 XHTML 执行类似的转换,使用 class 属性判断样式。本文在 ZIP 下载文件中提供了有关这种转换的示例(参见 下载)。
使用格式化信息
在某些情形下,指定样式信息是不可用的。对于 Word,不同用户可能使用不同的技术创建输入文档,包括直接应用字体更改而不是使用样式。类似地,在 HTML 中,作者或编写工具可能会对段落和其他元素应用不同的样式属性,而不是定义可以重用的 CSS 类。在这类情况下,要推测结构,则必须依靠文本格式化,比如字体大小和字体效果(如粗体和斜体)。这种做法在可靠性和一致性方面要逊色于样式,但是仍然可以提供重要的线索。
图 2 显示了一个使用直接格式化而非样式的 Word 文档。该文档的作者没有使用样式,而是对所有内容都采用 Normal 样式,直接修改字体大小,然后应用粗体和斜体使某些段落看上去类似于标题。
图 2. 使用格式化而非样式的 Word 文档

清单 14 中的 XSLT 根据 Word 文档的格式化信息而非样式名称将该文档转换为 XML 格式。它测试了字体的大小以及是否应用了粗体和斜体效果,从而判断标题是一级标题还是二级标题。在这种类型的转换中,样式映射就不是那么有用了,因为映射规则更加复杂,并且最适合使用 XSLT 和 XPath 代码表示。
清单 14. 从 XSLT 中的文本格式获得有关结构的提示
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" exclude-result-prefixes="w"> <xsl:output method="xml" indent="yes"/> <xsl:template match="/"> <document> <xsl:apply-templates select=".//w:p"/> </document> </xsl:template> <xsl:template match="w:p"> <xsl:variable name="size" select="w:pPr/w:rPr/w:sz/@w:val"/> <xsl:choose> <xsl:when test="($size > 32) and exists(w:pPr/w:rPr/w:b)"> <h1> <xsl:apply-templates select="*"/> </h1> </xsl:when> <xsl:when test="($size > 25) and exists(w:pPr/w:rPr/w:i)"> <h2> <xsl:apply-templates select="*"/> </h2> </xsl:when> <xsl:otherwise> <p> <xsl:apply-templates select="*" mode="char-formatting"/> </p> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="w:r" mode="char-formatting"> <xsl:choose> <xsl:when test="w:rPr/w:b"> <b> <xsl:apply-templates select="*"/> </b> </xsl:when> <xsl:when test="w:rPr/w:i"> <i> <xsl:apply-templates select="*"/> </i> </xsl:when> <xsl:otherwise> <xsl:apply-templates select="*"/> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet>
清单 15 展示了样例输出。
清单 15. Word 格式化 XSLT 的样例输出
<document> <h1>Chapter 1: In the beginning</h1> <p>In this chapter...</p> <h2>1.1 Introduction</h2> <p>In this section...</p> <h2>1.2 Next Steps</h2> <p>In this section there is text that uses <b>bold</b> and <i>italics</i>.</p> </document>
XHTML 中的一个类似应用就是使用 style
属性或格式化元素,如 font
和
center
。
注意事项和结束语
本文给出的所有示例都非常简单,主要用于培训目的。实际使用中遇到的内容可能要更加复杂。在某些场景下,可能会遇到非常一致的输入文档,例如,您将转换由生产编辑器认真纠正过的 Word 文档,或者由某个应用程序通过一致的方式生成的 XHTML 文档。
但通常情况下,内容都是杂乱无章的。如果内容是手工生成的,那么很可能存在许多变化。当您创建自己的 XSLT 时,不应当存有生成一致文档的侥幸。您需要频繁地对代码进行测试,编写捕捉未处理情形的模板并发出警告消息。
您应该特别关注混合内容。如果要转换包含混合内容的文档,一定要使用 apply-templates
而不是 value-of
,后者会不小心使混合内容变单调。
在处理叙述性内容时,空白区域也非常重要。避免在 XSLT 中对输出使用缩进,因为这可能会引入一些不希望看到的空白区。相反,避免从输入文档中删除空白,因为它们可能是有意放在那里的。
始终建议对您的输出进行检查。尽管检查大量的内容十分耗时,但是至少应该对输出进行抽查以找出重复错误。
下载资源
- 本文的样例 XSLT 样式表 (examples.zip | 21KB)
相关主题
- XSLT 是什么类型的语言?(Michael Kay,developerWorks,2005 年 4 月):通过这篇分析和概述性文章了解如何将 XSLT 放到上下文中。了解这种语言的起源,它的优点以及为什么应该使用它。
- “准备从 XSLT 1.0 升级到 2.0 ”(David Marston,Joanne Tong,Henry Zongaro;developerWorks,2006 年 10 月 - 2007 年 7 月):通过这个由七部分组成的系列文章,了解有关 XSLT 2.0 中高度受欢迎的更多特性,一些新特性以及其他特性旨在弥补 XSLT 1.0 缺失的特性。
- 第 1 部分: XSLT 的改进:通过将纯 1.0 语法的常见应用与更简单、更多样的 2.0 语法进行比较,了解哪些 XSLT 2.0 特性会促使您升级到 2.0。
- 第 2 部分: 从 XSLT 1.0 升级到 2.0 的五种策略:了解在计划升级到 XSLT 2.0 时的一些更高级的决策因素,为使用前向和后向兼容性作为过渡工具做好准备。
- 第 3 部分: 为什么需要制定迁移计划:查看购买 XSLT 2.0 处理器的指南。
- 第 4 部分: XSLT 可移植性工具箱:了解混合不同版本代码的完整工具箱。
- 第 5 部分: 使样式表可用于任何处理程序版本:了解在 1.0 和 2.0 之间可以迁移哪些样式表,以及如何在长期过渡期运行 1.0 和 2.0 处理器。
- 第 6 部分: 如何对 2.0 处理程序混合使用 XSLT 版本:了解如何以及在哪些情况下使用 1.0 的遗留代码获得与 2.0 处理器相同的效果。
- 第 7 部分: XSLT 2.0 中的部分特性,解决了 1.0 中的不足之处:了解如何应用 XSLT 2.0 增强实现数据组织、XPath 表达式语法扩展、跨模板参数传递、字符串处理等等。
- Saxon:下载用于测试本文示例的XSLT 2.0 处理器。
- HTML Tidy:下载可将 HTML 转化为格式良好的 XML 的开源解析器。
- More articles by this author(Priscilla Walmsley,developerWorks,2010 年 1 月至今):阅读有关 NIEM IEPD、XML 和其他技术的文章。
- developerWorks 中国网站 XML 技术专区:在 XML 专区中查找增强技能所需的资源,包括 DTD、模式和 XSLT。查看 XML 技术文档库,获得广泛的技术文章和技巧、教程、标准和 IBM 红皮书。
- developerWorks 技术活动 和 网络广播:随时关注这些活动中的技术。
- IBM 产品评估试用版软件:下载或 IBM SOA 人员沙箱,并开始使用来自 DB2®、Lotus®、Rational®、Tivoli® 和 WebSphere® 的应用程序开发工具和中间件产品。