XML开发技术——第五章
经过了上一次的学习,我们学到了用于查询的XPATH,它会在之后的很多地方予以应用。
比如今天我们要讲的XSLT
第五章 XSLT
本章内容的学习目的:
- 理解和掌握XML文档的转换过程。
- 学习如何使用XSLT中的模板实现XML文档的转换。
- 学习如何使用XSLT中的排序、循环、条件分支语句实现各种处理。
- 创建使用参数和变量的XSLT文档。
5.1 XSLT
Q1:什么是XSLT?
C1:XSLT(eXtensible Stylesheet Language Transformations),其中的T表示“转换”,它是一种专门用于对XML树型数据进行结构重组转换的有力工具,可以根据指定的转换规则(在XSLT中称之为模板)将一个XML文档树或者其中的部分内容转换为另一种文档树形式。
XSLT不仅局限于结构上的重组,它可以将XML文档转换为任何形式,包括XML、HTML和普通文本。
XSL是它的前身,本来包含了XML数据表达和数据转换。数据转换部分从中独立出来成为XSLT。剩下的数据表达部分成为XSL-FO
Q2:XSLT有什么注意事项?
C2:
- XSLT语言是一种声明性的语言,即XSLT程序本身只是包含了一些转换规则的XML文档。
- XSLT处理程序(或称之为执行引擎)将首先确定 XSLT规则,然后根据规则的匹配条件(通过XPath 表达式指定)、以及优先顺序完成相应的转换操作。
- XSLT本身也是一个XML文档,所以它必须严格遵守XML规范。其根元素的命名空间为
http://www.w3.org/1999/XSL/Transform
即:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
5.1.1 XSLT的工作原理
Q3:XSLT是怎样工作的?
E3:
C3:
- 在进行XSLT的转换任务时,需要两个输入文档,一个是包含源数据的XML文档,一个是包含转换任务规则的XSLT文档。
- 由XML解析器对这两个文档进行解析,将XML文档转换为所对应的文档树结构,将xslt(xsl)文档看作是一系列的转换规则。
- 由XSLT引擎调用这些规则,对文档树进行遍历,分别处理其中指定的数据节点,将其转换为所需的结果集,并序列化为结果文档。
5.1.2 XSLT的一个简单示例
1 |
|
5.2 XSLT中模板的创建以及内置模板的使用
5.2.1 XSLT中模板的声明
Q4:怎么声明模板?
E4:
C4:模板标记之间的内容相当于一个函数的函数体,表示在调用该模板时应该执行的具体操作。而元素开始标记中的属性match、name、mode和priority则用于描述该模板的相关信息。
Q5:模板有哪些属性?
C5:
- 匹配路径属性 match
在XSLT中,模板的调用分为两种方式:
●根据模板的匹配路径(在遍历的过程中)调用,具体又有两种情况:
i. 对于模板 xsl:template match=”/“,XSLT 处理器在碰到 XML 文档的文档节点时自动调用该模板,就好像作为程序执行的入口。
ii. 对于其他的模板match=other-pattern,将在模板xsl:template match=”/“的转换规则(函数体)中通过指出匹配路径的方式(使用xsl:apply-templates)进行隐式地或者显式地调用。
●根据模板名称属性,使用 xsl:call-template name=template-name 进行调用。
- 名称属性 name
模板
也可以使用name属性为模板指定一个名称,使其成为命名模板 。例
1 | <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> |
XSLT 处理器将调用命名模板 one(实际上名称 one 没有作用,因为是自动调用的),然后在模板 one 中使用 xsl:call-template 直接调用名为 another 的模板,在模板 another 执行结束之后,继续执行模板 one 的后续指令,这个过程非常类似于函数的调用。
- 模式属性 mode
- 优先级属性 priority
注意:XSLT中允许存在同名的模板;
当没有priority属性时,将执行后声明的模板;
有priority属性时,将使用 priority取值较大的模板。
- 返回类型属性 as
模板返回类型属性as的取值,表示该模板应该返回的数据类型。
注:该返回的XML元素包含了子元素和文本内容。
模板的返回类型属性as是一个可选的参数,如果不指定该参数,则模块可以输出任意的文本内容。
5.2.1 XSLT中模板的调用
1.使用xsl:apply-templates 调用模板
调用顺序:在广度优先、逐层向下的遍历过程中,指定继续遍历当前节点的所有子节点
完整语法:
1 | <xsl:apply-templates select=Expression mode=QName> |
对于xsl:apply-templates元素,select和mode属性都是可选的,即可以直接使用<xsl:apply-templates/>
对于上例,XSLT自动调用模板1,开始对整个XML文档树的遍历,即依次调用“处理指令”、“message元素”所对应的模板。所以模板1中使用了<xsl:apply-templates/>
,表示调用当前节点的所有子节点所对应的模板。若模板1中无<xsl:apply-templates/>
,遍历过程将中断,不会处理除文档节点”/“之外的任何节点。
下面介绍该元素的两个属性
- select(取值为一个XPath表达式)允许指定仅遍历当前节点的哪些子节点(以调用相应的模板)
例:<xsl:apply-templates select="message"/>
仅调用“message元素”所对应的模板
- mode属性指定需要在match属性取值相同的模板中,选择哪一个进行调用。
2.使用xsl:call-template 调用模板
在xsl:template元素开始标记和结束标记之间,使用 xsl:param元素为所在的模板声明参数,其as属性可以指定参数的数据类型。 例
注:用于为模板声明参数的xsl:param元素必须出现在模板正文的前面
在模板正文中,使用$+’模板参数名’来引用模板参数,以避免将其作为字符串进行处理。
5.2.2 XSLT中的内置模板
Q6:怎样分析内置模板?
E6:
C6:模板1’的match=“*|/”
是用于处理文档节点和所有元素节点(使用了通配符*),该模板的任务是调用所有子节点的处理模板。
模板2‘的match=“text()|@*”,
表示它用于处理文本节点和所有属性节点(使用了通配符@),由于文本节点和属性节点不可能再包含子节点,所以这个模板的任务是直接打印出当前节点(文本节点和属性节点)的内容(*
Q7:内置模板有什么作用?
C7:内置模板中仅对文本节点和属性节点进行了处理,即输出了其文本内容。其作用在于:让我们集中精力编写相关节点的处理模板,而无需过多地操心整个遍历过程中模板的逐层调用。只有在用户没有自定义处理某个节点的模块规则时,才会调用内置模块中的规则;否则,用户自定义的模块规则将覆盖内置模块中的规则。
Q8:内置模板存在什么问题?
E8:
C8:在Company模板中,<xsl:apply-templates/>
将调用其子节点(Name和Person)的处理模板。但这时不存在match=“Name”的模板(修改错误时则只需要加上空模板Name即可),于是调用默认模板(先1后2),输出了文本节点的内容,导致文本节点的内容输出了两次,而Person的子元素Name没有出现两次。
5.3 XSLT模板中各种转换功能的实现
5.3.1 value-of text
Q9:如何使用value-of?
E9:
1 | <message> |
C9:对于文本节点和属性节点,xsl:value-of select=“.” 当然提取的是文本节点的内容和属性节点的取值;对元素节点使用
Q10:如何输出空格?
E10:
C10:此时应该使用<xsl:text><xsl:text/>
。xsl:text元素开始标记和结束标记之间的内容会原封不动的输出到结果中,但是其中不能包含其他XML的标记。
5.3.2 xsl:for-each xsl:sort
Q11:怎么使用for-each与sort?
E11:
C11:例中选择出了所有person的子元素Name,并将它们进行排序,随后进行输出。
关于sort的语法:
1 | <xsl:sort select=expression |
5.3.3 xsl:if
Q12:怎么使用if?
E12:
C12:if通常与for-each搭配,根据条件输出所需要的文本或节点。
5.3.4 xsl:choose xsl:when xsl:otherwise
E13:
5.3.5 在输出中创建XML节点
Q13:如何使用copy和copy-of?
E13:
C13:在上例中,递归的使用了xsl:copy,用于复制每一个节点到结果树中。而xsl:copy-of直接在文档入口处复制了根元素和下面的整棵树(包括属性和子元素)到结果树中,二者存在以下差异:
缺点:xsl:copy 和 xsl:copy-of 可以将当前节点从源复制到输出,但是不能根据需要生成任意的 XML 节点。
Q14:如何使用element?
E14:
C14:上例通过xsl:element,将源文档中的message元素改名为了new-message
Q15:如何使用attribute?
E15:
C15:上例先通过copy复制了一个空的message元素,随后为其添加了属性content,并将原来message的文本内容赋给了content。
Q16:如何使用attribute-set?
E16:
5.3.6 如何控制输出格式?
E17:<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
C17:这表示输出为XML格式,版本为XML1.0,编码方式为UTF-8并且进行缩进,如果不进行缩进,输出的会写在同一行,难以体现出层次关系。
结
通过本次学习,我们学习到了XSLT的基本语法和其转换方式,在考试中XSLT常考于大题中,即给出原来的XML和XSLT让你写出转换后的XML文档。需要仔细学习规则,不然会失分很多。