我正在学习xslt group-by。我有一个样本xml如下
<?xml version="1.0" encoding="UTF-8"?>
<h1>
<a1>abcd</a1>
<a2>efgh</a2>
<h2>
<b1>IV-3</b1>
<b2>20.00</b2>
<h3>
<c1>VCH</c1>
<c2>1001</c2>
<c3>100.00</c3>
</h3>
</h2>
<h2>
<b1>IV-3</b1>
<b2>50.00</b2>
</h2>
<h2>
<b1>IV-3</b1>
<b2>10.00</b2>
<h3>
<c1>VCH</c1>
<c2>1001</c2>
<c3>300.00</c3>
</h3>
</h2>
<h2>
<b1>IV-3</b1>
<b2>30.00</b2>
</h2>
</h1>
我需要先将b1值分组并总结b2值,如果存在h3节点,则需要按c2分组并总结该组的c3值。我的xslt如下。
<?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:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="h1">
<t1>
<d1>
<xsl:value-of select="a1"/>
</d1>
<d2>
<xsl:value-of select="a2"/>
</d2>
<xsl:for-each-group select="h2" group-by="b1">
<xsl:if test="current-group()/count(h3) > 0 ">
<xsl:for-each-group select="current-group()/h3" group-by="c2">
<t2>
<e1>
<xsl:value-of select="../b1"/>
</e1>
<e2>
<xsl:value-of select="format-number(sum(current-group()/../b2),'#.00')"/>
</e2>
<e3>
<xsl:value-of select="format-number(sum(current-group()/c3),'#.00')"/>
</e3>
</t2>
</xsl:for-each-group>
</xsl:if>
<xsl:if test="current-group()/count(h3) = 0 ">
<t2>
<e1>
<xsl:value-of select="b1"/>
</e1>
<e2>
<xsl:value-of select="format-number(sum(current-group()/b2),'#.00')"/>
</e2>
<e3>
<xsl:value-of select="11111"/>
</e3>
</t2>
</xsl:if>
</xsl:for-each-group>
</t1>
</xsl:template>
</xsl:stylesheet>
如果h3不存在,我为e2获得的aggrigate值不正确。预期的结果是
<?xml version="1.0" encoding="UTF-8"?>
<t1 xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<d1>abcd</d1>
<d2>efgh</d2>
<t2>
<e1>IV-3</e1>
<e2>30.00</e2>
<e3>400.00</e3>
</t2>
<t2>
<e1>IV-3</e1>
<e2>80.00</e2>
<e3>11111</e3>
</t2>
</t1>
感谢您的帮助!
答案 0 :(得分:0)
您希望一次对两个值进行分组,因此您必须更改group-by
选择器。
这
<xsl:for-each-group select="h2" group-by="b1">
要
<xsl:for-each-group select="h2" group-by="concat(b1, '|', boolean(h3))">
除了您的代码有效。
<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:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:template match="h1">
<t1>
<d1>
<xsl:value-of select="a1" />
</d1>
<d2>
<xsl:value-of select="a2" />
</d2>
<xsl:for-each-group select="h2" group-by="concat(b1, '|', boolean(h3))">
<xsl:if test="current-group()/h3">
<xsl:for-each-group select="current-group()/h3" group-by="c2">
<t2>
<e1>
<xsl:value-of select="../b1" />
</e1>
<e2>
<xsl:value-of select="format-number(sum(current-group()/../b2), '#.00')" />
</e2>
<e3>
<xsl:value-of select="format-number(sum(current-group()/c3), '#.00')" />
</e3>
</t2>
</xsl:for-each-group>
</xsl:if>
<xsl:if test="not(current-group()/h3)">
<t2>
<e1>
<xsl:value-of select="b1" />
</e1>
<e2>
<xsl:value-of select="format-number(sum(current-group()/b2), '#.00')" />
</e2>
<e3>
<xsl:value-of select="11111" />
</e3>
</t2>
</xsl:if>
</xsl:for-each-group>
</t1>
</xsl:template>
</xsl:stylesheet>
此样式表生成所需的输出
<t1 xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
<d1>abcd</d1>
<d2>efgh</d2>
<t2>
<e1>IV-3</e1>
<e2>30.00</e2>
<e3>400.00</e3>
</t2>
<t2>
<e1>IV-3</e1>
<e2>80.00</e2>
<e3>11111</e3>
</t2>
</t1>
注释
boolean(h3)
根据'true'
元素的存在'false'
或<h3>
<xsl:if>
测试可以分别简化为current-group()/h3
和not(current-group()/h3)
(空节点集评估为false
)exclude-result-prefixes="xs fn"
以从输出文档中删除不必要的命名空间声明。