如何在 XSLT 1.0 中使用 XSLT 2.0 的分组依据功能?
How to use group-by functionality from XSLT 2.0 in XSLT 1.0?
我正在尝试在 XSLT 1.0 中使用 XSLT 2.0 中的分组依据功能。我有在 XSLT 2.0 中工作的代码,但我的处理器不处理 xslt 2.0。所以我需要一些帮助来使用 xslt 1.0 中的分组依据功能。
XML数据:
<table>
<row>
<month>03</month>
<year>2016</year>
<Id>10101</Id>
<Number>1</Number>
<code>A2004</code>
</row>
<row>
<month>03</month>
<year>2016</year>
<type>A</type>
<Id>10101</Id>
<Number>2</Number>
<code>A2004</code>
</row>
<row>
<month>04</month>
<year>2015</year>
<Id>10122</Id>
<Number>1</Number>
<code>A2004</code>
</row>
</table>
我正在尝试根据 ID 级别和其中的数字将此 xml 分组。
<test>
<xsl:for-each-group select="$table" group-by="Id">
<xsl:variable name="var2_resultof_group_items" as="item()+" select="current-group()"/>
</xsl:variable>
<row>
<xsl:attribute name="Id">
<xsl:value-of select="normalize-space(current-grouping-key())"/>
</xsl:attribute>
<xsl:for-each select="$var2_resultof_group_items">
<xsl:attribute name="month">
<xsl:value-of select="month"/>
</xsl:attribute>
</xsl:for-each>
<xsl:for-each select="$var2_resultof_group_items">
<xsl:attribute name="year">
<xsl:value-of select="year"/>
</xsl:attribute>
</xsl:for-each>
<xsl:for-each-group select="$var2_resultof_group_items" group-by="Number">
<xsl:variable name="var1_resultof_group_items" as="item()+" select="current-group()"/>
<line>
<xsl:attribute name="number" select="current-grouping-key()"/>
<xsl:for-each select="$var1_resultof_group_items">
<xsl:attribute name="code">
<xsl:value-of select="code"/>
</xsl:attribute>
</xsl:for-each>
</line>
</xsl:for-each-group>
</row>
</xsl:for-each-group>
</test>
这是我使用 xslt 2.0 代码得到的输出(所需输出),但我不确定如何使用 xslt 1.0 执行此操作
<test>
<row Id="10101" month="03" year="2016">
<line Number="1" code="A2004"/>
<line Number="2" code="A2004"/>
</row>
<row Id="10122" month="04" year="2015">
<line Number="1" code="A2004"/>
</row>
</test>
我可以使用 XLST 1.0 得到下面的输出,但我不确定如何实现 ID 分组,然后是其中的数字:
<test>
<row Id="10101" month="03" year="2016">
<line Number="1" code="A2004"/>
</row>
<row Id="10101" month="03" year="2016">
<line Number="2" code="A2004"/>
</row>
<row Id="10122" month="04" year="2015">
<line Number="1" code="A2004"/>
</row>
</test>
您可以试试这个 muenchian grouping XSLT 1.0 解决方案:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="kid" match="row" use="Id"/>
<xsl:template match="table">
<test>
<xsl:for-each select="row [
count ( key('kid',./Id)[1] | . ) = 1 ]">
<xsl:variable name="this" select="."/>
<row>
<xsl:attribute name="Id">
<xsl:value-of select="Id"/>
</xsl:attribute>
<xsl:attribute name="month">
<xsl:value-of select="month"/>
</xsl:attribute>
<xsl:attribute name="year">
<xsl:value-of select="year"/>
</xsl:attribute>
<xsl:for-each select="key('kid', $this/Id)">
<line>
<xsl:attribute name="number" >
<xsl:value-of select="Number"/>
</xsl:attribute>
<xsl:attribute name="code">
<xsl:value-of select="code"/>
</xsl:attribute>
</line>
</xsl:for-each>
</row>
</xsl:for-each>
</test>
</xsl:template>
</xsl:stylesheet>
具有以下输出:
<test>
<row Id="10101" month="03" year="2016">
<line number="1" code="A2004"/>
<line number="2" code="A2004"/>
</row>
<row Id="10122" month="04" year="2015">
<line number="1" code="A2004"/>
</row>
</test>
这是一个更简单、更短且几乎完全采用“push”风格的解决方案:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:key name="kRowById" match="row" use="Id"/>
<xsl:template match="/*">
<test>
<xsl:apply-templates/>
</test>
</xsl:template>
<xsl:template match="row[generate-id() = generate-id(key('kRowById', Id)[1])]">
<row id="{Id}">
<xsl:apply-templates select="key('kRowById', Id)" mode="inGroup"/>
</row>
</xsl:template>
<xsl:template match="row" mode="inGroup">
<line Number="{Number}" code="{code}"/>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
当此转换应用于提供的 XML 文档时:
<table>
<row>
<month>03</month>
<year>2016</year>
<Id>10101</Id>
<Number>1</Number>
<code>A2004</code>
</row>
<row>
<month>03</month>
<year>2016</year>
<type>A</type>
<Id>10101</Id>
<Number>2</Number>
<code>A2004</code>
</row>
<row>
<month>04</month>
<year>2015</year>
<Id>10122</Id>
<Number>1</Number>
<code>A2004</code>
</row>
</table>
产生了想要的、正确的结果:
<test>
<row id="10101">
<line Number="1" code="A2004"/>
<line Number="2" code="A2004"/>
</row>
<row id="10122">
<line Number="1" code="A2004"/>
</row>
</test>
解释:
Muenchian 分组。
使用标准 XSLT 函数generate-id()
进行节点身份比较。
使用 AVT(属性值模板)
使用模式。
使用 XSLT 内置(又名 "default")模板。
我正在尝试在 XSLT 1.0 中使用 XSLT 2.0 中的分组依据功能。我有在 XSLT 2.0 中工作的代码,但我的处理器不处理 xslt 2.0。所以我需要一些帮助来使用 xslt 1.0 中的分组依据功能。
XML数据:
<table>
<row>
<month>03</month>
<year>2016</year>
<Id>10101</Id>
<Number>1</Number>
<code>A2004</code>
</row>
<row>
<month>03</month>
<year>2016</year>
<type>A</type>
<Id>10101</Id>
<Number>2</Number>
<code>A2004</code>
</row>
<row>
<month>04</month>
<year>2015</year>
<Id>10122</Id>
<Number>1</Number>
<code>A2004</code>
</row>
</table>
我正在尝试根据 ID 级别和其中的数字将此 xml 分组。
<test>
<xsl:for-each-group select="$table" group-by="Id">
<xsl:variable name="var2_resultof_group_items" as="item()+" select="current-group()"/>
</xsl:variable>
<row>
<xsl:attribute name="Id">
<xsl:value-of select="normalize-space(current-grouping-key())"/>
</xsl:attribute>
<xsl:for-each select="$var2_resultof_group_items">
<xsl:attribute name="month">
<xsl:value-of select="month"/>
</xsl:attribute>
</xsl:for-each>
<xsl:for-each select="$var2_resultof_group_items">
<xsl:attribute name="year">
<xsl:value-of select="year"/>
</xsl:attribute>
</xsl:for-each>
<xsl:for-each-group select="$var2_resultof_group_items" group-by="Number">
<xsl:variable name="var1_resultof_group_items" as="item()+" select="current-group()"/>
<line>
<xsl:attribute name="number" select="current-grouping-key()"/>
<xsl:for-each select="$var1_resultof_group_items">
<xsl:attribute name="code">
<xsl:value-of select="code"/>
</xsl:attribute>
</xsl:for-each>
</line>
</xsl:for-each-group>
</row>
</xsl:for-each-group>
</test>
这是我使用 xslt 2.0 代码得到的输出(所需输出),但我不确定如何使用 xslt 1.0 执行此操作
<test>
<row Id="10101" month="03" year="2016">
<line Number="1" code="A2004"/>
<line Number="2" code="A2004"/>
</row>
<row Id="10122" month="04" year="2015">
<line Number="1" code="A2004"/>
</row>
</test>
我可以使用 XLST 1.0 得到下面的输出,但我不确定如何实现 ID 分组,然后是其中的数字:
<test>
<row Id="10101" month="03" year="2016">
<line Number="1" code="A2004"/>
</row>
<row Id="10101" month="03" year="2016">
<line Number="2" code="A2004"/>
</row>
<row Id="10122" month="04" year="2015">
<line Number="1" code="A2004"/>
</row>
</test>
您可以试试这个 muenchian grouping XSLT 1.0 解决方案:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="kid" match="row" use="Id"/>
<xsl:template match="table">
<test>
<xsl:for-each select="row [
count ( key('kid',./Id)[1] | . ) = 1 ]">
<xsl:variable name="this" select="."/>
<row>
<xsl:attribute name="Id">
<xsl:value-of select="Id"/>
</xsl:attribute>
<xsl:attribute name="month">
<xsl:value-of select="month"/>
</xsl:attribute>
<xsl:attribute name="year">
<xsl:value-of select="year"/>
</xsl:attribute>
<xsl:for-each select="key('kid', $this/Id)">
<line>
<xsl:attribute name="number" >
<xsl:value-of select="Number"/>
</xsl:attribute>
<xsl:attribute name="code">
<xsl:value-of select="code"/>
</xsl:attribute>
</line>
</xsl:for-each>
</row>
</xsl:for-each>
</test>
</xsl:template>
</xsl:stylesheet>
具有以下输出:
<test>
<row Id="10101" month="03" year="2016">
<line number="1" code="A2004"/>
<line number="2" code="A2004"/>
</row>
<row Id="10122" month="04" year="2015">
<line number="1" code="A2004"/>
</row>
</test>
这是一个更简单、更短且几乎完全采用“push”风格的解决方案:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:key name="kRowById" match="row" use="Id"/>
<xsl:template match="/*">
<test>
<xsl:apply-templates/>
</test>
</xsl:template>
<xsl:template match="row[generate-id() = generate-id(key('kRowById', Id)[1])]">
<row id="{Id}">
<xsl:apply-templates select="key('kRowById', Id)" mode="inGroup"/>
</row>
</xsl:template>
<xsl:template match="row" mode="inGroup">
<line Number="{Number}" code="{code}"/>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
当此转换应用于提供的 XML 文档时:
<table>
<row>
<month>03</month>
<year>2016</year>
<Id>10101</Id>
<Number>1</Number>
<code>A2004</code>
</row>
<row>
<month>03</month>
<year>2016</year>
<type>A</type>
<Id>10101</Id>
<Number>2</Number>
<code>A2004</code>
</row>
<row>
<month>04</month>
<year>2015</year>
<Id>10122</Id>
<Number>1</Number>
<code>A2004</code>
</row>
</table>
产生了想要的、正确的结果:
<test>
<row id="10101">
<line Number="1" code="A2004"/>
<line Number="2" code="A2004"/>
</row>
<row id="10122">
<line Number="1" code="A2004"/>
</row>
</test>
解释:
Muenchian 分组。
使用标准 XSLT 函数
generate-id()
进行节点身份比较。使用 AVT(属性值模板)
使用模式。
使用 XSLT 内置(又名 "default")模板。