[XML]学习笔记(七)XSLT

一、XSL(eXtensible Stylesheet Language)扩展样式表语言:主要包含三个部分——XSLT用于XML文档转换,XPath用于在XML文档中导航,XSL-FO用于XML文档格式化。

注意:XSL样式表本身也是一个XML文档,所以第一行必须为XML声明。

二、XSLT = XSLTransformations XSL转换,可将一种XML文档转换为另一种XML文档,或者说XSLT将XML源树转换为XML结果树,通过使用XPath来定义源文档中可匹配一个或多个预定义模板部分,一旦匹配被找到,XSLT就会调用模板将源文档中的匹配部分转换为结果文档。

三、XSLT是一种闭包,它的输入和输出都是树,可以管道化利用,如:文档1 -> 文档2-> 文档3。

四、XSLT语法:XSL样式表由一个或多个模板(template)的规则组成,每个模板含有当前某个指定节点被匹配时所应用的规则。

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

XSLT的根元素,用于定义该文档是一个XSLT样式表,上例中包含版本号以及XSLT命名空间两个属性。其中stylesheet也可写为transform,两者是完全相同的。

b) <xsl:import href="sourcePath"/>和<xsl:import href="sourcePath"/>

在根元素下,第一个<xsl:template>之前植入,用于直接引用外部的其他xsl。

区别在于当定义的规则和正文中的规则冲突时,import的规则优先级较低,include的规则优先级与正文的规则相同。

如:原book.xsl中有

<xsl:template match="title">
Title
</xsl:template>

而另一个anotherBook.xsl中有include该文件,则NewTitle是无效的,依旧使用原模板中的Title。如果采用import,则可以覆盖原有book.xsl中的模板。

<xsl:include href="book.xsl">
(:<xsl:import href="book.xsl">:)
<xsl:template match="title">
NewTitle
</xsl:template>

c) <xsl:template math=”…”>元素

每个xsl样式表中至少包含一个,用于构造模板,match属性的值是XPath表达式,用于为整个模板定义文档,其中采用”/” 表示定义整个文档。可选用属性name,该属性将在后面用于模板重用。

d) <xsl:apply-templates select="expression" mode="name">元素

把一个模板应用于当前元素或其子元素。

通过select属性可以筛选匹配的元素或其子元素,*表示要选取整个节点集,省略该属性时选取当前结点的所有子节点。缺省情况下相当于select="text()",即选取文本。

通过mode属性用来区分相同元素的不同处理方法。

其中<xsl:apply-templates/>是默认执行该模板,当在和叶子节点相关联的模板中,可以不必写明。

如:用对cd下的title和artist分别应用模板,模板cd、title和artist中省略了<xsl:apply-templates/>。

<xsl:template match="cd">
<p>
<xsl:apply-templates select="title"/>
<xsl:apply-templates select="artist"/>
</p>
</xsl:template>

<xsl:template match="title">
Title: <span style="color:#ff0000">
<xsl:value-of select="."/></span>
<br />
</xsl:template>

<xsl:template match="artist">
Artist: <span style="color:#00ff00">
<xsl:value-of select="."/></span>
<br />
</xsl:template>

e) <xsl:value-of>元素

用于提取某个选定节点的内容,可以是文本、元素或者属性,并把值添加到转换的输出流中。可拥有属性select,该属性的值为一个XPath表达式。

如:下面的xsl语句选出了catalog/cd/title和catalog/cd/artist的值。

      <td><xsl:value-of select="catalog/cd/title"/></td>
      <td><xsl:value-of select="catalog/cd/artist"/></td>

f) <xsl:for-each>元素

用于选取指定节点集中的每个元素。与value-of类似,它也有select属性,其值也是一个XPath表达式,当然在表达式中添加谓词作为判别式也可以用来筛选元素。

如:下面的xsl语句选出了artist为Bob Dylan的cd信息。

<xsl:for-each select="catalog/cd[artist=‘Bob Dylan‘]">

合法的比较运算符:= (等于),!= (不等于),&lt; (小于),&gt; (大于)

g) <xsl:sort>元素

用于对结果进行排序,紧跟<xsl:apply-templates>或<xsl:for-each>,是它们内部的一个元素,而不是属性。

sort可以拥有以下属性:

i. select="XPath",规定节点的排序关键字,即根据哪个节点/节点集排序。

ii. lang="language",规定排序所采用的语言。

iii. data-type = { "text" | "number" | QName },规定排序所采用的数据类型,默认为text。text是按所选节点的文本类型排序,即字典序;number则是按照所选节点的数据类型排序,如30,6,132按照text得到132,30,6,按照number得到6,30,132。

iv. order={"ascending"|"descending"},规定排序的顺序,默认为"ascending"。

v. case-order={"upper-first"|"lower-first"},规定是否首先按照大写/小写字母排序,比如选用了lower-first,则对于book,Book,CZ,cz排序结果为book,Book,cz,CZ。

如:根据artist的值排序。

	<xsl:for-each select="catalog/cd">
      <xsl:sort select="artist"/>
      <tr>
        <td><xsl:value-of select="title"/></td>
        <td><xsl:value-of select="artist"/></td>
      </tr>
      </xsl:for-each>

h) <xsl:if>元素

在<xsl:for-each>内部,它包含了一个“模板”,用于对XML文档内容的条件测试,只有在指定的条件成立时才会应用模板。

有且只有一个属性test,该属性的值为一个表达式,规定了要测试的条件。

如:找出售价大于10元的cd的名称和作者。

	<xsl:for-each select="catalog/cd">
      <xsl:if test="price > 10">
        <tr>
          <td><xsl:value-of select="title"/></td>
          <td><xsl:value-of select="artist"/></td>
        </tr>
      </xsl:if>
      </xsl:for-each>

以下xsl语句显示的效果是最后一张cd的title输出后面跟!,倒数第二张和最后一张cd的title之间用“,and”连接,其余用逗号连接。

注意:xsl语句的每个if语句都会被测试!

    <xsl:for-each select="catalog/cd">
      <xsl:value-of select="title"/>
      <xsl:if test="position()!=last()">
        <xsl:text>, </xsl:text>
      </xsl:if>
      <xsl:if test="position()=last()-1">
        <xsl:text> and </xsl:text>
      </xsl:if>
      <xsl:if test="position()=last()">
        <xsl:text>!</xsl:text>
      </xsl:if>
    </xsl:for-each>

i) <xsl:choose>元素

与<xsl:when>和<xsl:otherwise>结合,进行多重测试。只有when元素有且只有一个test属性。

基本语法:

<xsl:choose>
  <xsl:when test="expression">
    ... Output ...
  </xsl:when>
<xsl:when test="expression">
    ... Output ...
  </xsl:when>
  <xsl:otherwise>
    ... Output ...
  </xsl:otherwise>
</xsl:choose>

注意:when不会像if一样对一个测试点进行多次测试,好比switch-case语句加上break。

如:一个名为color的变量,如果当前测试的元素有color属性,则将color变量的值赋给当前测试元素的color属性;否则,将color属性置为green。

<xsl:variable name="color">
  <xsl:choose>
    <xsl:when test="@color">
      <xsl:value-of select="@color"/>
    </xsl:when>
    <xsl:otherwise>green</xsl:otherwise>
  </xsl:choose>
</xsl:variable>

j) <xsl:call-template>元素:

<xsl:call-template name="templateName">用于实现模板重用。

k) <xsl:number/>元素:

用于测定当前节点在源文档中的位置,也可用于将格式化的数字插入结果树。

i. count=”xPathExpression”:可选属性,指定要计算的节点。

ii. level:可选属性,控制如何分配序号。

1. single——默认,即每个序号只与所在层序号有关;

2. multiple——每个序号包含层级关系;

3. any——所有层共用一个序号关系。

iii. format:格式标记,可为1数字计数,01与1唯一的区别在于01~09,a表示小写字母计数,A表示大写字母计数,i表示小写罗马数字计数,I表示大写罗马数字计数。

iv. value:自己提供数字代替产生的序号;

grouping-separator:规定采用什么符号来分割数字或组,默认为“,”;

grouping-size:规定分组的大小,默认为3。

如:

<xsl:number value="123456" grouping-separator="." grouping-size="2"/>

输出为12.34.56

<xsl:number value="12" grouping-size="1" grouping-separator="#" format="I"/>

输出为X#I#I,首先将12转换成大写罗马数字XII,然后对其进行分割。

如源books.xml为:

<?xml version="1.0" encoding="UTF-8"?>
<list>
	<book ID="666">
		<chapter>First Chapter</chapter>
		<chapter>Second Chapter
			<chapter>Subchapter 1</chapter>
			<chapter>Subchapter 2</chapter>
		</chapter>
		<chapter>Third Chapter
			<chapter>Subchapter A</chapter>
			<chapter>Subchapter B
				<chapter> subsub a</chapter>
				<chapter> subsub b</chapter>
			</chapter>
		</chapter>
	</book>
</list>

目标输出为:

转换的xsl为:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
	<xsl:template match="/">
		<xsl:for-each select="//chapter">
			<br/>
			<xsl:number level="multiple" format="1.A.a "/>
			<xsl:value-of select="./text()"/>
		</xsl:for-each>
	</xsl:template>
</xsl:stylesheet>

如果将level选为single,则输出结果如下:

1 First Chapter

2 Second Chapter

1 Subchapter 1

2 Subchapter 2

3 Third Chapter

1 Subchapter A

2 Subchapter B

1 subsub a

2 subsub b

如果将level选为any,则输出结果如下:

1 First Chapter

2 Second Chapter

3 Subchapter 1

4 Subchapter 2

5 Third Chapter

6 Subchapter A

7 Subchapter B

8 subsub a

9 subsub b

l) <applet>属性值模板:

如:

<applet>
	<code class="Applet"/>
	<codebase>/src/code</codebase>
</applet>
<xsl:template match="/">
	<xsl:apply-templates select="applet">
		<applet code="{code/@class}" codebase="{codebase}/java"/>
	</xsl:apply-templates>
</xsl:stylesheet>

实际效果为:

<applet code="Applet" codebase="src/code/java"/>

五、 XML与XSL关联:

<?xml-stylesheet type="text/xsl" href="***.xslt"?>

六、 XSL参数:<xsl:with-param name="…">

定义了传递给模板的参数的值,with-param的name属性的值必须与所调用的模板的param的name属性值相匹配,否则将被忽略。call-template和apply-templates中允许使用with-param元素。可以通过元素的内容设置参数值(如例子中),也可以通过select属性赋值。

如:

输入repeatTest.xml:

<?xml version="1.0" encoding="UTF-8"?>
<Name>
	<AAA repeat="3"/>
	<BBB repeat="2"/>
	<CCC repeat="5"/>
</Name>

转换repeatTest.xml:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
<xsl:template match="/Name/*">
	<p>
		<xsl:call-template name="while">
			<xsl:with-param name="test">
				<xsl:value-of select="@repeat"/>
			</xsl:with-param>
		</xsl:call-template>
	</p>
</xsl:template>
<xsl:template name="while">
	<xsl:param name="test"/> #test记录了repeat的次数
	<xsl:value-of select="name()"/> #输出AAA或BBB或CCC
	<xsl:text/>
	<xsl:if test="$test!=1"> #判断当前repeat属性是否为1
		<xsl:call-template name="while">
			<xsl:with-param name="test">
				<xsl:value-of select="$test - 1"/> #递归调用while模板,参数修正为test值减1,注意$test和-、-和1之间均有空格
			</xsl:with-param>
		</xsl:call-template>
	</xsl:if>
</xsl:template>
</xsl:stylesheet>

输出结果:

AAAAAAAAA

BBBBBB

CCCCCCCCCCCCCCC

七、 XSL变量:<xsl:variable name="…">

用于声明局部变量/全局变量,如果被声明为顶层元素则是全局的,如果在模板内部声明则为局部的。一旦设置了变量的值,就无法改变或修改该值,但可以通过其内容或select属性向变量添加值。注意:如果设置了select属性则variable不能包含任何内容了。

如:仍对上面的books.xml进行取每一层的最后一个chapter操作:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
	<xsl:variable name="totalChapters">
		<xsl:value-of select="//chapter[last()]"/>
	</xsl:variable>
	<xsl:template match="/">
		<xsl:value-of select="$totalChapters"/>
	</xsl:template>
</xsl:stylesheet>

操作结果:注意Third Chapter被应用了此模板,因此递归调用。

Subchapter 2

Third Chapter

Subchapter A

Subchapter B

subsub a

subsub b

Subchapter B

subsub a

subsub b

subsub b

八、 XSL中的key元素<xsl:key name="name" match="pattern" use="expression">

该元素是顶层元素,可以为指定的元素分配名称和值对,通过key()函数在样式表中使用。但此处的key不必是唯一的。

三个属性均为必需的,name规定键的名称,match规定键被应用到哪个节点,use指定要作为该键的值使用的表达式。

如定义一个键来寻找作者含有Jim Blue的书的所有作者:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
	<xsl:key name="findAuthor" match="list/book" use="author"/>

	<xsl:param name="author">Jim Blue</xsl:param>
	<xsl:template match="/">
		<xsl:copy-of select="key('findAuthor', $author)"/>
	</xsl:template>
</xsl:stylesheet>

源keyTest.xml:

<?xml version="1.0" encoding="UTF-8"?>
<list>
	<book ID="234">
		<author>Jim Blue</author>
		<author>Dan Farm</author>
		<author>Blue Flowers</author>
	</book>
	<book ID="666">
		<author>Mark Simp</author>
		<author>Jim Blue</author>
		<author>Green Trees</author>
	</book>
	<book ID="898">
		<author>Jay Bart</author>
		<author>Red Tulips</author>
	</book>
</list>

输出结果:

Jim Blue

Dan Farm

Blue Flowers

Mark Simp

Jim Blue

Green Trees

九、通过XSLT与XQuery生成HTML

给定students.xml文件,按照出生年月日排序,学号为Z00123101的学生信息用绿色显示,学号为Z00123102的学生信息用蓝色显示,其余用红色显示。

源students.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<students>

     <student id="Z00123101">
              <name>The No.1 student</name>
              <birthday>1987.2</birthday>
              <phone>62220001</phone>
     </student>

     <student id="Z00123102">
              <name>the No.2 student</name>
              <birthday>1975.6</birthday>
              <phone>62220002</phone>
     </student>

     <student id="Z00123103">
              <name>the No.3 student</name>
              <birthday>1978.8</birthday>
              <phone>62220003</phone>
     </student>

     <student id="Z00123104">
              <name>the No.4 student</name>
              <birthday>1976.2</birthday>
              <phone>62220004</phone>
     </student>

</students>

通过XSLT生成:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
     <xsl:template match="/">
              <html>
                       <head>
                               <table border="1" cols="4" width="100%">
                               <tr>
                                        <th>No</th>
                                        <th>Name</th>
                                        <th>Phone</th>
                                        <th>Birthday</th>
                               </tr>
                               <xsl:for-each select="students/student">
                               <xsl:sort select="birthday"/>
                               <xsl:choose>
                                        <xsl:when test="@id='Z00123101'">
                                                 <tr style="color:green">
                                                          <td><xsl:value-of select="@id"/></td>
                                                          <xsl:apply-templates select="name|phone"/>
                                                          <xsl:apply-templates select="birthday"/>
                                                 </tr>
                                        </xsl:when>
                                        <xsl:when test="@id='Z00123102'">
                                                 <tr style="color:blue">
                                                          <td><xsl:value-of select="@id"/></td>
                                                          <xsl:apply-templates select="name|phone"/>
                                                          <xsl:apply-templates select="birthday"/>
                                                 </tr>
                                        </xsl:when>
                                        <xsl:otherwise>
                                        <tr style="color:red">
                                                 <td><xsl:value-of select="@id"/></td>
                                                 <xsl:apply-templates select="name|phone"/>
                                                 <xsl:apply-templates select="birthday"/>
                                        </tr>
                                        </xsl:otherwise>
                               </xsl:choose>
                               </xsl:for-each>
                               </table>
                       </head>
                       <body></body>
              </html>
     </xsl:template>
     <xsl:template match="name|phone|birthday">
              <td><xsl:value-of select="."></xsl:value-of></td>
     </xsl:template>

</xsl:stylesheet>

通过XQuery生成:

xquery version "1.0";
<html>
    <head>
        <table border="1" cols="4" width="100%">
                       <tr>
                               <th>No</th>
                               <th>Name</th>
                               <th>Phone</th>
                               <th>Birthday</th>
                       </tr>
            {
            for $x in doc("students.xml")/students/student
                               order by $x/birthday
                return if(data($x/@id)="Z00123102")
                then <tr style="color:blue">
                    <td>{data($x/@id)}</td>
                    <td>{data($x/name)}</td>
                    <td>{data($x/phone)}</td>
                    <td>{data($x/birthday)}</td>
                </tr>
                else if(data($x/@id)="Z00123101")
                then <tr style="color:green">
                    <td>{data($x/@id)}</td>
                    <td>{data($x/name)}</td>
                    <td>{data($x/phone)}</td>
                    <td>{data($x/birthday)}</td>
                </tr>
                else <tr style="color:red">
                    <td>{data($x/@id)}</td>
                    <td>{data($x/name)}</td>
                    <td>{data($x/phone)}</td>
                    <td>{data($x/birthday)}</td>
                </tr>
            }
        </table>
    </head>
    <body/>
</html>
 
时间: 2024-10-13 10:59:51

[XML]学习笔记(七)XSLT的相关文章

XML学习笔记之:XSLT &lt;xsl:variable&gt; 元素

声明:该笔记引自W3School! 1.<xsl:variable> 元素用于声明局部或全局的变量. 2.可以通过 <xsl:variable> 元素的内容或通过 select 属性,向变量添加值! 3.一旦设置了变量的值,就无法改变或修改该值! <xsl:variable name="name" select="expression"> <!-- Content:template --> </xsl:varia

xml学习笔记 6.XQuery

XQuery xml query 是一种专门用于xml半结构化数据的查询语言,是W3C的推荐的标准语言. XQuery是有一些SQL专家制定的,基本语法与sql语句非常相似.比xslt更加简单. FLOWR语句与select语句相对应,完成对xml数据的查询,筛选和排序.FLOWR是指FOR,LET,WHERE,ORDERBY,RETURN五种语句.其中可以使用XPATH路径表达式以及xpath中的内置函数,各种自定义的函数,和命名空间. for子句: for $b in doc("bib-de

第十七篇:博采众长--初探WDDM驱动学习笔记(七)

基于WDDM驱动的DirectX视频加速重定向框架设计与实现 现在的研究生的论文, 真正质量高的, 少之又少, 开题开得特别大, 动不动就要搞个大课题, 从绪论开始到真正自己所做的内容之间, 是东拼西凑地抄概念, 抄公式, 达到字数篇幅的要求, 而自己正真做了什么, 有哪些实际感受, 做出的内容, 相比前面的东拼西凑就几点内容, 之后就草草结束, 步入感谢的段落. 原因不光只有学生自己, 所谓的读研, 如果没有一个环境, 学生有再大的愿望, 再强的毅力, 到头来也只是空无奈. 有些导师要写书,

马哥学习笔记七——LAMP编译安装之MYSQL

1.准备数据存放的文件系统 新建一个逻辑卷,并将其挂载至特定目录即可.这里不再给出过程. 这里假设其逻辑卷的挂载目录为/mydata,而后需要创建/mydata/data目录做为mysql数据的存放目录. 2.新建用户以安全方式运行进程: # groupadd -r mysql # useradd -g mysql -r -s /sbin/nologin -M -d /mydata/data mysql # chown -R mysql:mysql /mydata/data 3.安装并初始化my

Lua学习笔记(七):迭代器与泛型for

1.迭代器与闭包 迭代器是一种支持指针类型的结构,它可以遍历集合的每一个元素.在Lua中我们常常使用函数来描述迭代器,每次调用该函数就返回集合的下一个元素. 迭代器需要保留上一次成功调用的状态和下一次成功调用的状态,也就是他知道来自于哪里和将要前往哪里.闭包提供的机制可以很容易实现这个任务.记住:闭包是一个内部函数,它可以访问一个或者多个外部函数的外部局部变量.每次闭包的成功调用后这些外部局部变量都保存他们的值(状态).当然如果要创建一个闭包必须要创建其外部局部变量.所以一个典型的闭包的结构包含

python学习笔记七:条件&循环语句

1.print/import更多信息 print打印多个表达式,使用逗号隔开 >>> print 'Age:',42 Age: 42   #注意个结果之间有一个空格符 import:从模块导入函数 import 模块 from 模块 import 函数 from 模块 import * 如果两个模块都有open函数的时候, 1)使用下面方法使用: module1.open()... module2.open()... 2)语句末尾增加as子句 >>> import ma

swift学习笔记(七)自动引用计数

与Object-c一样,swift使用自动引用计数来跟踪并管理应用使用的内存.当实例不再被使用时,及retainCount=0时,会自动释放是理所占用的内存空间. 注:引用计数仅适用于类的实例,因为struct和enumeration属于值类型,也就不牵涉引用,所以其存储和管理方式并不是引用计数. 当一个实例被初始化时,系统会自动分配一定的内存空间,用于管理属性和方法.当实例对象不再被使用时,其内存空间被收回. swift中的引用类型分为三种,即Strong强引用,weak弱引用和无主引用unw

XML学习笔记(五):使用 jdom和dom4j 解析XML

XML解析的详细分析与jaxp解析XML详见:XML学习笔记(四):使用 DOM和SAX 解析XML 一.JDom 1.创建XML文件: 1)Document类即代表整个XML文档,把生成的 Document 利用 XMLOutputter 类输出即可. 2)映射关系:元素:Element:属性:Attribute:注解:Comment:文本信息:Text: 3)注意:addContent()是追加,setContent()会覆盖. /** * 创建XML * * @throws IOExcep

Swift学习笔记七:闭包

闭包可以 捕获 和存储其所在上下文中任意常量和变量的引用. Swift 会为您管理在 捕获 过程中涉及到的内存操作. 在 函数 章节中介绍的全局和嵌套函数实际上也是特殊的闭包,闭包采取如下三种形式之一: 1. 全局函数是一个有名字但不会捕获任何值的闭包 2. 嵌套函数是一个有名字并可以捕获其封闭函数域内值的闭包 3. 闭包表达式是一个可以捕获其上下文中变量或常量值的没有名字的闭包 一.闭包表达式 闭包函数类似于Objective-C中的block.下面我们用事实说话: let counts =

Linux System Programming 学习笔记(七) 线程

1. Threading is the creation and management of multiple units of execution within a single process 二进制文件是驻留在存储介质上,已被编译成操作系统可以使用,准备执行但没有正运行的休眠程序 进程是操作系统对 正在执行中的二进制文件的抽象:已加载的二进制.虚拟内存.内核资源 线程是进程内的执行单元 processes are running binaries, threads are the smal