XSL基础
W3C Recommendation XSLT Version 1.0
XSL:不仅仅是一个样式表
XSL包含3部分:
一个转换XML文档的方法;
一个定义XML部分和模式的方法;
一个格式化XML文档的方法。
如果对此还不能理解,那么可以先将XSL理解成:一种将XML转换成HTML的语言,一种可以过滤和分类XML数据的语言,一种可以对一个XML文档的部分进行寻址的语言,一种可以基于数据值格式化XML数据的语言(如用红色显示负数),一种向不同设备输出XML数据的语言(如屏幕、纸或声音)。
XSL是三种语言的结合体
XSL实际上包含三种语言,具体是:
XSLT是一种转换XML的语言;
XPath是一种定义XML部分或模式的语言;
XSL格式化对象是一种定义XML显示方式的语言。
XSLT是一种用来将XML文档转换成其他类型文档或其它XML文档的语言。XPath是一种对XML文档的部分进行寻址的语言。设计XPath是要让XSLT使用的。格式化是将一个XSL转换的结果变成适于读者或听众使用的输出格式的过程。
XSLT:XSL转换
XSLT是XSL标准中最重要的部分,它用于将一个XML文档转换成另一个XML文档或另一种类型的文档,也就是将一个XML文档转换成浏览器所能识别的一种格式。这其中之一就是HTML。通常,XSLT将每个XML元素都转换成一个HTML元素。
XSLT还可以向输出文件中增加全新的元素,或去掉一些元素。它可以重新安排这些元素并对元素进行分类,测试并确定显示哪些元素等等。
描述这种转换过程的一个常用说法是:XSL用XSLT将一个XML来源树转换成另一个XML结果树(或将一个XML源文档转换成另一个XML结果文档)。
在准备XML 文档以备显示的过程中执行的任务可以分成两个阶段:转换和格式化。转换是将一个 XML 文档(或其内存中的表示法)转换成另一个 XML 文档的过程。格式是将已转换的树状结构转换成两维图形表示法或可能是一维音频流的过程。XSLT 是为控制第一阶段“转换”而开发的语言。实际上,大多数人现在使用 XSL 将 XML 文档转换成 HTML,并使用 HTML 浏览器作为格式化引擎。这是可行的,因为 HTML 实际上只是 XML 词汇表的一个示例,而 XSLT 可以使用任何 XML 词汇表作为其目标。
将转换成一种语言和格式化成另一种语言这两个操作分离经证实的确是一种好的决策,因为转换语言的许多应用程序经证明无法向用户显示文档。
XSLT 与 XML 的关系,就好象 SQL 与表格化数据的关系一样。关系模型的强大功能并非来自用表存储数据的思想,而是源于 SQL 中可行的基于关系运算的高级数据操作。同样,XML 的层次化数据模型对应用程序开发者的帮助实际上也非常小。正是因为 XSLT 作为 XML 数据的高级操作语言提供了如此强大的功能。
XSL如何工作
在转换的过程中,XSLT用XPath来定义源文档中与一个或多个预先确定的模板相匹配的部分。当找到了一个匹配时,XSLT就将源文档中的匹配部分转换成结果文档;而源文档中不与任何一个模板匹配的部分最终在结果中保持不变。
XSL使用模板等
XSL使用一个或多个模板来定义如何输出XML元素,用一个匹配属性(路径运算符)来将模板与一个XML元素联系起来,还可以用匹配属性来为XML文档的一个完整分支来定义模板。
<xsl:template match=" "> </xsl:template>
<xsl:value-of select=" "/>
<xsl:for-each select=" "> </xsl:for-each>
<xsl:apply-templates />
<xsl:sort select=" "/>
<xsl:if test=" ">
<xsl:choose>
<xsl:when test=" ">... some code ... </xsl:when>
<xsl:otherwise>... some code .... </xsl:otherwise>
... <xsl:otherwise>... some code .... </xsl:otherwise>...
</xsl:choose>
XSL命名空间
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
客户端XSL:如何用XML解析器在客户机上将XML文档转换成HTML文档。
一个JavaScript的解决方法
在前文中,我们解释了如何用XSL将一个文档从XML转换成HTML。窍门就是向XML文件中增加一个XSL样式表,然后让浏览器来进行转换。即使这种方法能奏效,在XML文件中包含一个样式表引用也并非令人满意的方法,并且在不支持XSL的浏览器上这种方法还不能奏效。
一个更通用的方法应该是用一个JavaScript来进行从XML到HTML的转换。使用一个JavaScript,就更有以下可能性:
允许JavaScript进行浏览器细节测试;
根据浏览器和用户需求使用不同的样式表。
这就是XSL的美妙之处。XSL设计目的之一就是使数据从一个格式转换成另一个格式成为可能,从而支持不同的浏览器和不同的用户需求。
客户端XSL转换将成为未来浏览器工作任务的一个主要部分,我们还将看到专业化浏览器市场的成长,比如Braille、发声网络、网络打印机、手持PC、移动电话等。
确保XML文件没有对XSL文件的引用,XSL文件也没有对XML文件的引用。注意:上面的句子说明一个XML文件可以用许多不同的XSL文件进行转换。
<body>
<script language="javascript">
// Load XML
var xml = new ActiveXObject("Microsoft.XMLDOM")
xml.async = false
xml.load("cd_catalog.xml")
// Load the XSL
var xsl = new ActiveXObject("Microsoft.XMLDOM")
xsl.async = false
xsl.load("cd_catalog.xsl")
// Transform
document.write(xml.transformNode(xsl))
</script>
</body>
</html>
服务器端XSL:如何用XML解析器在服务器上将XML文档转换成HTML文档。
服务器端XSL
由于不是所有的浏览器都支持XML和XSL,因此就有了一个在服务器上将XML转换成HTML的方法。
一个跨浏览器的解决方法
在前面的章节中,我们解释了如何用XSL在浏览器中将XML文档转换成HTML,窍门就是让JavaScript使用一个XML解析器来进行转换。但是当浏览器不支持XML解析器时,这种方法是不奏效的。要使XML数据对所有浏览器都可用,我们就必须在服务器上转换XML文档,并将它作为纯HTML发送到浏览器。
这是XSL的另一个美妙之处。XSL的设计目的之一是使得在服务器上将数据从一种格式转换成另一种格式成为可能,并将可读数据返回到所有未来的浏览器中。
在服务器上进行XSL转换正在成为未来Internet信息服务器工作任务的一个主要部分,同时我们将看到专用浏览器市场的发展,如:Braille、有声网络、网络打印机、手持PC、移动电话等。
要确保XML文件没有对XSL文件的引用,XSL文件也没有对XML文件的引用。同时请注意:上面的句子表明一个服务器上的XML文件可以用许多不同的XSL文件进行转换。
'Load the XML
set xml = Server.CreateObject("Microsoft.XMLDOM")
xml.async = false
xml.load(Server.MapPath("cd_catalog.xml"))
'Load the XSL
set xsl = Server.CreateObject("Microsoft.XMLDOM")
xsl.async = false
xsl.load(Server.MapPath("cd_catalog.xsl"))
'Transform the file
Response.Write(xml.transformNode(xsl))
%>
XSL索引:将XML文档转换成HTML之前,如何用XML解析器来对XML文档进行索引。
要想将这个XML文件作为一个普通的HTML文件输出,并且同时对它进行索引:
标准地,使用<xsl:sort select=" "/>。
而对于IE5,只需要在XSL文件中增加一个order-by 属性,如下:<xsl:for-each select="CATALOG/CD" order-by="+ ARTIST">
order-by属性使用加号(+)或减号(-)来定义是使用升序还是降序,再用一个元素名称来定义排序的元素。
XSL过滤器:将XML文档转换成HTML之前,如何用XML解析器过滤XML文档。
要过滤XML文件,只需要为XSL文件中的for-each元素的选择属性增加一个过滤器,如下:
<xsl:for-each select="CATALOG/CD[ARTIST='Bob Dylan']">
合法的过滤器操作符是:
= 等于
!= 不等于
< 小于
> 大于
XSLT is a Programming Language
From a programmer's point of view, XSLT is a programming language for processing XML data — that is, transforming XML documents. As such, it supports the following:
A small set of flexible data types: Boolean, number, string, node-set, and external objects.
A full set of operations: <xsl:template>, <xsl:apply-templates>, <xsl:sort>, <xsl:output>, and so on.
Programming flow-control: <xsl:if>, <xsl:for-each>, <xsl:choose>, and so on.
An important feature of XSLT programming: It is rule-based and declarative. In XSLT, rules are called template rules. A template rule is an instruction to transform a specified source element in a particular way. To transform a set of data, you must provide a complete set of rules. However, each rule is independent of every other.
基本处理范例是模式匹配。XSLT 继承了文本处理语言(如 Perl)的传统,XSLT 样式表包括一组模板规则,每条规则都使用以下方式:“如果在输入中遇到此条件,则生成下列输出。”规则的顺序是无关紧要的,当有几条规则匹配同一个输入时,将应用冲突解决算法。然而,XSLT 与串行文本处理语言的不同之处是 XSLT 对输入并非逐行进行处理。实际上,XSLT 将输入 XML 文档视为树状结构,每条模板规则都适用于树中的一个节点。模板规则本身可以决定下一步处理哪些节点,因此不必按输入文档的原始顺序来扫描输入。
XSLT 处理器的操作
XSLT 处理器使用树状结构作为其输入,并生成另一个树状结构作为输出。XSLT 输入和输出的树状结构:
常常通过对 XML 文档进行语法分析来生成输入树状结构,而输出树状结构通常被串行化到另一个 XML 文档中。但 XSLT 处理器本身操作的是树状结构,而不是 XML 字符流。这个概念对理解如何执行更复杂的转换起关键de作用。首先,它表示 XSLT 处理器可以理解源文档中与树状结构无关的特殊之处。例如,无论属性是包括在单引号中还是在双引号中,都不可能应用不同的处理,因为会将这两种形式视为同一个基本文档的不同表示方法。更深入地看,它表示处理输入元素或生成输出元素是一个原子操作。不可能将处理元素的开始标记和结束标记分成单独的操作,因为一个元素会自动表示成树模型的单节点。
XSLT 使用叫作 XPath 的子语言来引用输入树中的节点。XPath 本质上是与具有层次结构的 XML 数据模型相匹配的查询语言。它可以通过按任何方向浏览树来选择节点,并根据节点的值和位置应用谓词。它还包括用于基本字符串处理、数字计算和布尔代数的工具。例如,XPath 表达式 ../@title
选择当前节点的父代元素的标题属性。XPath 表达式用于选择要进行处理的输入节点、在条件处理期间测试条件,以及计算值以便插入结果树中。模板规则中还使用了 XPath 表达式的简化形式“模式”来定义特定模板规则适用于哪些节点。XPath 在单独的 W3C 推荐书中定义,它允许使用在其它上下文中再使用的查询语言,特别是用于定义扩展超链接的 XPointer。
XSLT 以传统语言(如 Lisp、Scheme)中的功能性编程的概念为基础。样式表由模板组成,这些模板基本上是单一功能 -- 每个模板将输出树的一部分定义成一部分输入树的功能,并且不产生副作用。使用无副作用的规则受到严格控制(除了转义成用类似 Java 的语言编写的外部代码)。XSLT 语言允许定义变量,但不允许现有变量更改它的值 -- 即没有赋值语句。这个策略使许多新用户感到困惑,其目的是为了允许逐步应用样式表。其原理是如果语言没有副作用,那么对输入文档做很小的改动时,不必从头执行整个转换就应该可以计算出对输出文档的最后更改。目前必须说这只是理论上的可能,任何现有 XSLT 处理器还不能实现。(注:虽然 XSLT 以功能性编程概念为基础,但它还不是一个完整的功能性编程语言,因为它缺少将函数当作一级数据类型进行处理的能力。)
与使用低级 DOM 和 SAX 接口编码的过程性应用程序相比,用于转换 XML 数据结构的 XSLT 应用程序更能适应对 XML 文档细节的更改。在数据库世界中,这种特性叫做数据独立性,正是由于数据独立性导致了诸如 SQL 之类声明性语言的成功,并使旧的引导性数据访问语言走向衰亡。我坚信在 XML 世界中也会这样。
当然与所有声明性语言一样,XSLT 也会降低性能。但是对于大多数应用程序,今天的 XSLT 处理器的性能已经完全能够满足应用程序的需要,并且它会变得越来越好。
XSLT Elements Reference
Note:
NN/IE: indicates the earliest version of Netscape or Internet Explorer that supports the tag.
All elements supported in IE 5.X may have NON-standard behavior, because IE 5.X was released before XSLT became a W3C Recommendation!
Element | Description | IE | NN |
---|---|---|---|
apply-imports | Applies a template rule from an imported style sheet | 6.0 | |
apply-templates | Applies a template rule to the current element or to the current element's child nodes | 5.0 | 6.0 |
attribute | Adds an attribute | 5.0 | 6.0 |
attribute-set | Defines a named set of attributes | 6.0 | 6.0 |
call-template | Calls a named template | 6.0 | 6.0 |
choose | Used in conjunction with <when> and <otherwise> to express multiple conditional tests | 5.0 | 6.0 |
comment | Creates a comment node in the result tree | 5.0 | 6.0 |
copy | Creates a copy of the current node (without child nodes and attributes) | 5.0 | 6.0 |
copy-of | Creates a copy of the current node (with child nodes and attributes) | 6.0 | 6.0 |
decimal-format | Defines the characters and symbols to be used when converting numbers into strings, with the format-number() function | 6.0 | |
element | Creates an element node in the output document | 5.0 | 6.0 |
fallback | Specifies an alternate code to run if the processor does not support an XSLT element | 6.0 | |
for-each | Loops through each node in a specified node set | 5.0 | 6.0 |
if | Contains a template that will be applied only if a specified condition is true | 5.0 | 6.0 |
import | Imports the contents of one style sheet into another. Note: An imported style sheet has lower precedence than the importing style sheet | 6.0 | 6.0 |
include | Includes the contents of one style sheet into another. Note: An included style sheet has the same precedence as the including style sheet | 6.0 | 6.0 |
key | Declares a named key that can be used in the style sheet with the key() function | 6.0 | 6.0 |
message | Writes a message to the output (used to report errors) | 6.0 | 6.0 |
namespace-alias | Replaces a namespace in the style sheet to a different namespace in the output | 6.0 | |
number | Determines the integer position of the current node and formats a number | 6.0 | 6.0 |
otherwise | Specifies a default action for the <choose> element | 5.0 | 6.0 |
output | Defines the format of the output document | 6.0 | 6.0 |
param | Declares a local or global parameter | 6.0 | 6.0 |
preserve-space | Defines the elements for which white space should be preserved | 6.0 | 6.0 |
processing-instruction | Writes a processing instruction to the output | 5.0 | 6.0 |
sort | Sorts the output | 6.0 | 6.0 |
strip-space | Defines the elements for which white space should be removed | 6.0 | 6.0 |
stylesheet | Defines the root element of a style sheet | 5.0 | 6.0 |
template | Rules to apply when a specified node is matched | 5.0 | 6.0 |
text | Writes literal text to the output | 5.0 | 6.0 |
transform | Defines the root element of a style sheet | 6.0 | 6.0 |
value-of | Extracts the value of a selected node | 5.0 | 6.0 |
variable | Declares a local or global variable | 6.0 | 6.0 |
when | Specifies an action for the <choose> element | 5.0 | 6.0 |
with-param | Defines the value of a parameter to be passed into a template | 6.0 | 6.0 |
XSLT Functions
Name | Description |
current() | Returns the current node |
document() | Used to access the nodes in an external XML document |
element-available() | Tests whether the element specified is supported by the XSLT processor |
format-number() | Converts a number into a string |
function-available() | Tests whether the function specified is supported by the XSLT processor |
generate-id() | Returns a string value that uniquely identifies a specified node |
key() | Returns a node-set using the index specified by an <xsl:key> element |
system-property() | Returns the value of the system properties |
unparsed-entity-uri() | Returns the URI of an unparsed entity |
XPath Function Library
Node Set Functions
Name | Description | Syntax |
count() | Returns the number of nodes in a node-set | number=count(node-set) |
id() | Selects elements by their unique ID | node-set=id(value) |
last() | Returns the position number of the last node in the processed node list | number=last() |
local-name() | Returns the local part of a node. A node usually consists of a prefix, a colon, followed by the local name | string=local-name(node) |
name() | Returns the name of a node | string=name(node) |
namespace-uri() | Returns the namespace URI of a specified node | uri=namespace-uri(node) |
position() | Returns the position in the node list of the node that is currently being processed | number=position() |
String Functions
Name | Description | Syntax & Example |
concat() | Returns the concatenation of all its arguments | string=concat(val1, val2, ..)
Example: |
contains() | Returns true if the second string is contained within the first string, otherwise it returns false |
bool=contains(val,substr) Example: |
normalize-space() | Removes leading and trailing spaces from a string, and replaces all internal sequences of white with one white space | string=normalize-space(string)
Example: |
starts-with() | Returns true if the first string starts with the second string, otherwise it returns false | bool=starts-with(string,substr)
Example: |
string() | Converts the value argument to a string | string(value)
Example: |
string-length() | Returns the number of characters in a string | number=string-length(string)
Example: |
substring() | Returns a part of the string in the string argument | string=substring(string,start,length)
Example: |
substring-after() | Returns the part of the string in the string argument that occurs after the substring in the substr argument |
string=substring-after(string,substr) Example: |
substring-before() | Returns the part of the string in the string argument that occurs before the substring in the substr argument |
string=substring-before(string,substr) Example: |
translate() | Performs a character by character replacement. It looks in the value argument for characters contained in string1, and replaces each character for the one in the same position in the string2 | string=translate(value,string1,string2)
Examples: translate('12:30','03','54') translate('12:30','0123','abcd') |
Number Functions
Name | Description | Syntax & Example |
ceiling() | Returns the smallest integer that is not less than the number argument | number=ceiling(number)
Example: |
floor() | Returns the largest integer that is not greater than the number argument |
number=floor(number) Example: |
number() | Converts the value argument to a number |
number=number(value) Example: |
round() | Rounds the number argument to the nearest integer | integer=round(number)
Example: |
sum() | Returns the total value of a set of numeric values in a node-set | number=sum(nodeset)
Example: |
Boolean Functions
Name | Description | Syntax & Example |
boolean() | Converts the value argument to Boolean and returns true or false | bool=boolean(value) |
false() | Returns false | false()
Example: |
lang() | Returns true if the language argument matches the language of the xsl:lang element, otherwise it returns false | bool=lang(language) |
not() | Returns true if the condition argument is false, and false if the condition argument is true | bool=not(condition)
Example: |
true() | Returns true | true()
Example: |
last()
――返回一个称为上下文大小的数字,即给定上下文中的节点数,相当于最后一个节点的位置数。position()
――返回一个称为上下文位置的数字,集当前节点在给上下文节点集(列表)中的位置。比如,可以用表达式position()=last()
测试处理的是否是集合中的最后一个节点。id(object)
――返回一个节点集,根据在 DTD 中声明为 ID 类型的唯一标识符选择元素。因为在 AuctionItemList.xml 中没有使用 DTD,这个例子中得到的节点集总是空集。Id("ItemId0001")
返回一个空节点集。string()
――把参数对象或者上下文结点转化成字符串。合法的参数包括节点集、数字、布尔值或者其他任何类型――但是对于最后一种情况转换的结果不可预料。建议使用 XSLT 函数format-number
把数字转化成字符串,或者使用 XSLT 元素xsl:number
提供给用户。starts-with()
――如果第一个字符串参数以第二个字符串参数开始则返回 true,否则返回 false。比如,starts-with("Miles Smiles album, CD", "Miles")
返回 true。boolean()
――根据以下规则返回作为参数传递的对象转换成布尔值的结果:不同于 0 或者NaN
的数字为 true;非空的节点集或者字符串为 true。其他类型的对象已不可预料的方式转换。not()
――如果作为参数传递的布尔值为 false 返回 true,否则返回 false。true()
和false()
――分别返回 true 或 false。这些函数很有用,因为在 XPath 中 true 和 false 被看作是普通的字符串而不是真和假的值。lang()
――如果上下文节点的语言和字符串参数中指定的语言相同,或者是它的一种子语言返回 true,否则返回 false。上下文节点的语言通过xml:lang
属性的值定义。比如,lang("en")
对于 AuctionItemList.xml 树中的任何节点都返回 false,因为没有指定xml:lang
属性。- number()――把可选的对象参数(如果没有指定参数则使用上下文节点)转化成数字,转换的规则如下:
- 布尔值 true 转换成1,false 转换成 0。
- 字符串转换成合理的数字。
- 节点集首先转换成字符串,然后把这个字符串转换成数字。
number("250")
返回 250,而number("miles1965")
返回NaN
。