您的位置:首页 > 其它

XSLT2.0 xsl:for-each-group用法详解.

2016-09-27 23:11 302 查看
for-each-group是在XSLT2.0中增加进来的一个标签.其主要作用是对结果进行分组.

由此增加了current-group()和current-grouping-key()两个内置函数.用于判断当前for-each中元素的序列以及识别号.

<xs:element name="for-each-group" substitutionGroup="xsl:instruction">
<xs:complexType mixed="true">
<xs:complexContent mixed="true">
<xs:extension base="xsl:versioned-element-type">
<xs:sequence>
<xs:element ref="xsl:sort" minOccurs="0" maxOccurs="unbounded"/>
<xs:group ref="xsl:sequence-constructor-group" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="select" type="xsl:expression" use="required"/>
<xs:attribute name="group-by" type="xsl:expression"/>
<xs:attribute name="group-adjacent" type="xsl:expression"/>
<xs:attribute name="group-starting-with" type="xsl:pattern"/>
<xs:attribute name="group-ending-with" type="xsl:pattern"/>
<xs:attribute name="collation" type="xs:anyURI"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>

对于xsl:for-each-group来做.select属性是是必选的.
group-by/group-adjacent/group-starting-with/group-ending-with这四个属性选择其中一个用于赋值current-group()以及current-grouping-key()

例子:

source文件:people.xml内容如下:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- source of people.xml -->
<people>
<person sex="female">
<firstname>Jennie</firstname>
<lastname>Lin</lastname>
</person>
<person sex="male">
<firstname>Ricky</firstname>
<lastname>Lin</lastname>
</person>
<person sex="male">
<firstname>Peter</firstname>
<lastname>Li</lastname>
</person>
<person sex="female">
<firstname>Fang</firstname>
<lastname>Lin</lastname>
</person>

<person sex="female">
<firstname>FangFang</firstname>
<lastname>Wu</lastname>
</person>
<person sex="male">
<firstname>Paul</firstname>
<lastname>Lin</lastname>
</person>
</people>

对应的XSLT文件:people.xslt
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:myFunction="http://www.ricky.com/myFunction"
exclude-result-prefixes="xs myFunction">
<xsl:output indent="yes"/>
<xsl:variable name="people" select="document('people.xml')"/>
<!--
Date:2016-09-27
XSLT Processor: Saxon
command: java net.sf.saxon.Transform -xsl:people.xslt -it:main -o:people.html
-->
<xsl:template name="main">
<!-- group-by: sex attribute -->
<xsl:result-document href="people-group1.xml">
<people>
<xsl:comment>
sort the people group by the sex attribute.
</xsl:comment>
<xsl:for-each-group select="$people/people/person" group-by="@sex">
<!-- sort by sex(female > male) -->
<xsl:sort select="current-grouping-key()" order="ascending"/>
<sex value="{current-grouping-key()}">
<xsl:for-each select="current-group()">
<xsl:sort select="firstname"/>
<xsl:sort select="lastname"/>
<person firstname="{firstname}" lastname="{lastname}"/>
</xsl:for-each>
</sex>
</xsl:for-each-group>
</people>
</xsl:result-document>
<!-- group-adjacent : lastname is 'Lin' or other-->
<xsl:result-document href="people-group2.xml">
<people>
<xsl:comment>
sort the people by the lastname. 'Lin' in first group,other in the second group
</xsl:comment>
<xsl:variable name="sort-people" select="myFunction:sort-people()"/>
<xsl:for-each-group select="$sort-people/people/person" group-adjacent="if (normalize-space(lastname) = 'Lin') then ('lin') else ('other')">
<!-- current-grouping-key is either 'lin' or 'other' -->
<xsl:sort select="current-grouping-key()"/>
<group index="{position()}" group-key="{current-grouping-key()}">
<xsl:for-each select="current-group()">
<person firstname="{firstname}" lastname="{lastname}"/>
</xsl:for-each>
</group>
</xsl:for-each-group>
</people>
</xsl:result-document>

<!-- group-starting-with: lastname start with 'Li' -->

<xsl:result-document href="people-group3.xml">
<people>
<xsl:for-each-group select="$people/people/person" group-starting-with="*[(position() - 1) mod 4 = 0]">
<group index="{position()}">
<xsl:for-each select="current-group()">
<person firstname='{firstname}' lastname="{lastname}"/>
</xsl:for-each>
</group>
</xsl:for-each-group>
</people>
</xsl:result-document>

<!-- test -->
<xsl:variable name="sort-people" select="myFunction:sort-people()"/>
<people>
<xsl:for-each select="$sort-people/people/person">
<person firstname="{firstname}" lastname="{lastname}"/>
</xsl:for-each>
</people>
</xsl:template>

<xsl:function name="myFunction:sort-people">
<!-- sort the people by lastname element. -->
<xsl:variable name="sort-people">
<people>
<xsl:perform-sort select="$people/people/person">
<xsl:sort select="myFunction:mysort(lastname,'Lin')"/>
</xsl:perform-sort>
</people>
</xsl:variable>
<xsl:copy-of select="$sort-people"/>
</xsl:function>

<xsl:function name="myFunction:mysort" as="xs:integer">
<xsl:param name="node"/>
<xsl:param name="value" as="xs:string"/>
<xsl:value-of select="if (normalize-space($node) = $value) then 0 else 1"/>
</xsl:function>
</xsl:stylesheet>

group-by属性常见的用法是以select序列中的节点的某个属性作为分组的条件.条件相同的节点作为同一个组中的序列.
属性实例执行结果参照生成的:people-group1.xml文件
group-adjacent属性这通过子定义的方式告诉解析器分组的规则.(不同组的current-grouping-key()可以相同.)如上例中告诉解析器lastname='Lin'的当成一组,其余的当成另一组来对待.注:上面例子中通过两个自定义方法对people中的person进行了重新排序.否则生成结果将不止两个组. 属性实例执行结果参照生成的:people-group2.xml文件

group-starting-with与group-ending-with的用法有点类似,但是结果相反.group-starting-with告诉解析器判断分组的起点.如上面的例子中告诉解析器当(position() - 1) mod 4 = 0 的条件符合的话那么就分组.其结果就是person节点会每四个为一个组.属性实例执行结果参照生成的:people-group3.xml文件
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息