一个XSLT的变量、参数和模板调用的问题
1. 问题
昨天遇到了这样一个xml文档,如下:bookObject.xml
<?xml version="1.0" encoding="ASCII"?>
<?xml-stylesheet type="text/xsl" href="Book2PubXSLT.xsl"?>
<xmi:XMI xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI">
<Book title="WxbBook">
<chapters nbPages="12" title="chapter1" author="author1"/>
<chapters nbPages="15" title="chapter2" author="author2"/>
<chapters nbPages="20" title="chapter3" author="author3"/>
</Book>
<Book title="nextBook">
<chapters nbPages="10" title="chapter1" author="aaa"/>
<chapters nbPages="20" title="chapter2" author="bbb"/>
<chapters nbPages="30" title="chapter3" author="ccc"/>
</Book>
</xmi:XMI>
希望能够使用XSLT转换为这样的一个xml文档(目的是为了做一个很简单的模型转换实例,当然这点和本文主题几乎无关):publicationObject.xml
<?xml version="1.0" encoding="ASCII"?>
<xmi:XMI xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns="Publication">
<Publication title="nextBook" nbPages="60" authors="ccc and aaa and bbb"/>
<Publication title="WxbBook" nbPages="47" authors="author3 and author1 and author2"/>
</xmi:XMI>
分析这两个文档可以看出,希望的转换规则如下:
Book节点有一个属性title,它等于Publication的节点属性title。
Book节点包含chapters子节点,每个子节点都有三个属性。其中一个Book节点的所有chapters子节点的nbPages属性相加等于Publication的nbPages属性;
一个Book节点的所有chapters子节点的author相连,并在中间插入and则等于Publication的authors属性。
由于之前我并没有接触过XSLT的变量、参数和xsl:call-template等概念,所以还是颇费了一点时间来解决此问题。
2. 问题的解决
值得注意的有几点:
1. XSLT中的变量一次赋值后是不能改变的,所以这里的变量几乎等于其它语言中的常量。
2. template有两种,常见的是通过<xsl:template match="/">这样的方式定义的,使用match属性。调用的时候是使用<xsl:apply-templates select=""/>。另一种template类似与其它语言中的函数调用,使用<xsl:template name=”t_name”>来定义,调用的时候使用<xsl:call-template name=" t_name "/>来调用。
3. 在第二种template的定义中可以加入参数,类似于其它编程语言中的参数列表。在调用时也可以传入具体的值做为实参。
4. 由于XSLT不包含for、while等循环语句。当简单的for-each不能满足要求时。则需要使用递归template调用来完成其它语言中的循环。从functional programming的理论中我们知道这二者是等价的。
下面是进行转换的XSL文档:Book2PubXSLT.xsl
<?xml version="1.0" encoding="ASCII"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:xmi="http://www.omg.org/XMI">
<xsl:template name="left">
<xsl:text disable-output-escaping="yes"><</xsl:text>
</xsl:template>
<xsl:template name="right">
<xsl:text disable-output-escaping="yes">></xsl:text>
</xsl:template>
<xsl:template match="/">
<xsl:call-template name="left"/>xmi:XMI xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns="Publication"<xsl:call-template name="right"/>
<xsl:apply-templates select="xmi:XMI"/>
<xsl:call-template name="left"/>/xmi:XMI<xsl:call-template name="right"/>
</xsl:template>
<xsl:template match="xmi:XMI">
<xsl:for-each select="Book">
<xsl:call-template name="left"/>Publication title="<xsl:value-of select="@title"/>"
nbPages ="<xsl:value-of select="sum(chapters/@nbPages)"/>"
authors ="
<xsl:call-template name="concatAuthor">
<xsl:with-param name="str" select="chapters/@author"/>
<xsl:with-param name="index" select="1"/>
<xsl:with-param name="nodenum" select="last()+1"/>
</xsl:call-template>"/<xsl:call-template name="right"/>
</xsl:for-each>
</xsl:template>
<xsl:template name="concatAuthor">
<xsl:param name="str"/>
<xsl:param name="index"/>
<xsl:param name="nodenum"/>
<xsl:choose>
<xsl:when test="$index != $nodenum">
<xsl:call-template name="concatAuthor">
<xsl:with-param name="str" select="concat($str,' and ',chapters[$index+1]/@author)"/>
<xsl:with-param name="index" select="$index + 1"/>
<xsl:with-param name="nodenum" select="$nodenum"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$str"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
从上面可以看出,解决问题最主要的一点就是使用了一个递归模板concatAuthor,它带有三个参数str,index 和nodenum,分别表示连接的字符串、迭代子和chapters的节点数。通过这种方法,熟悉递归的人可以很快的写出几乎和javascript等价的种种数据操作。当然,由于变量不能赋值、参数只能以递归的方式来改动,还是很不方便的。
其优点也是明显的,不依赖其它脚本语言完成了数据操作。可以在所有xsl引擎上面运行。
3. 小结
深入讲解XSLT的中文文献不多,大多数是入门级的。当我半猜半试的解决了这个问题后。发现了在O’Reilly有一本《XSLT》的书,其中列出了这样的内容。
出处:http://www.blogjava.net/wxb_nudt/archive/2006/03/08/34377.html
关注我】。(●'◡'●)
如果,您希望更容易地发现我的新博客,不妨点击一下绿色通道的【因为,我的写作热情也离不开您的肯定与支持,感谢您的阅读,我是【Jack_孟】!
本文来自博客园,作者:jack_Meng,转载请注明原文链接:https://www.cnblogs.com/mq0036/archive/2012/07/18/2597845.html
【免责声明】本文来自源于网络,如涉及版权或侵权问题,请及时联系我们,我们将第一时间删除或更改!
posted on 2012-07-18 17:48 jack_Meng 阅读(2362) 评论(0) 编辑 收藏 举报