XSLT根据必须动态计算的值对xml进行排序
我必须根据几个值对xml文件进行排序。输入xml具有以下结构:XSLT根据必须动态计算的值对xml进行排序,xml,sorting,xslt,xslt-grouping,Xml,Sorting,Xslt,Xslt Grouping,我必须根据几个值对xml文件进行排序。输入xml具有以下结构: 100 2000 30003 100 2000 30001 100 1000 30002 100 1000 30004 100 1000 30010 200 3000 30006 200 4000 30009 200 4000 30007 200 3000 30005 此xml应按类别排序,然后按ProductNr排序,但应按ProductGroup分组。这意味着,如果ProductGroup 2000中的ProductNr
100
2000
30003
100
2000
30001
100
1000
30002
100
1000
30004
100
1000
30010
200
3000
30006
200
4000
30009
200
4000
30007
200
3000
30005
此xml应按类别排序,然后按ProductNr排序,但应按ProductGroup分组。这意味着,如果ProductGroup 2000中的ProductNr小于ProductGroup 1000中的ProductNr,则ProductGroup 2000应在ProductGroup 1000之前打印
输出xml应如下所示:
100
2000
30001
100
2000
30003
100
1000
30002
100
1000
30004
100
1000
30010
200
3000
30005
200
3000
30006
200
4000
30007
200
4000
30009
现在,我的想法是根据以下逻辑生成一个用于排序的密钥:
key=Category+(ProductGroup中最小的ProductNr)+ProductNr
然后我可以按此键进行排序并得到正确的结果
我是XSLT新手,不知道如何计算ProductGroup中最小的ProductNr,然后按此值排序。你能给我一个提示吗
或者:是否有更好的技术来解决此任务?这应该可以:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:key name="kProdInGroup" match="ProductNr" use="../ProductGroup" />
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*">
<xsl:copy>
<xsl:apply-templates select="Product">
<!-- First sort by Category -->
<xsl:sort select="Category" data-type="number" />
<!-- Then by the min ProductNr per group -->
<xsl:sort select="key('kProdInGroup', ProductGroup)
[not(. > key('kProdInGroup', ../ProductGroup))]"
data-type="number" />
<!-- Then by ProductNr -->
<xsl:sort select="ProductNr" data-type="number" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
应用于示例输入时,结果为:
<DataSet>
<Product>
<Category>100</Category>
<ProductGroup>2000</ProductGroup>
<ProductNr>30001</ProductNr>
</Product>
<Product>
<Category>100</Category>
<ProductGroup>2000</ProductGroup>
<ProductNr>30003</ProductNr>
</Product>
<Product>
<Category>100</Category>
<ProductGroup>1000</ProductGroup>
<ProductNr>30002</ProductNr>
</Product>
<Product>
<Category>100</Category>
<ProductGroup>1000</ProductGroup>
<ProductNr>30004</ProductNr>
</Product>
<Product>
<Category>100</Category>
<ProductGroup>1000</ProductGroup>
<ProductNr>30010</ProductNr>
</Product>
<Product>
<Category>200</Category>
<ProductGroup>3000</ProductGroup>
<ProductNr>30005</ProductNr>
</Product>
<Product>
<Category>200</Category>
<ProductGroup>3000</ProductGroup>
<ProductNr>30006</ProductNr>
</Product>
<Product>
<Category>200</Category>
<ProductGroup>4000</ProductGroup>
<ProductNr>30007</ProductNr>
</Product>
<Product>
<Category>200</Category>
<ProductGroup>4000</ProductGroup>
<ProductNr>30009</ProductNr>
</Product>
</DataSet>
100
2000
30001
100
2000
30003
100
1000
30002
100
1000
30004
100
1000
30010
200
3000
30005
200
3000
30006
200
4000
30007
200
4000
30009
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:key name="kProdInGroup" match="ProductNr" use="../ProductGroup" />
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*">
<xsl:copy>
<xsl:apply-templates select="Product">
<!-- First sort by Category -->
<xsl:sort select="Category" data-type="number" />
<!-- Then by the min ProductNr per group -->
<xsl:sort select="key('kProdInGroup', ProductGroup)
[not(. > key('kProdInGroup', ../ProductGroup))]"
data-type="number" />
<!-- Then by ProductNr -->
<xsl:sort select="ProductNr" data-type="number" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
<DataSet>
<Product>
<Category>100</Category>
<ProductGroup>2000</ProductGroup>
<ProductNr>30001</ProductNr>
</Product>
<Product>
<Category>100</Category>
<ProductGroup>2000</ProductGroup>
<ProductNr>30003</ProductNr>
</Product>
<Product>
<Category>100</Category>
<ProductGroup>1000</ProductGroup>
<ProductNr>30002</ProductNr>
</Product>
<Product>
<Category>100</Category>
<ProductGroup>1000</ProductGroup>
<ProductNr>30004</ProductNr>
</Product>
<Product>
<Category>100</Category>
<ProductGroup>1000</ProductGroup>
<ProductNr>30010</ProductNr>
</Product>
<Product>
<Category>200</Category>
<ProductGroup>3000</ProductGroup>
<ProductNr>30005</ProductNr>
</Product>
<Product>
<Category>200</Category>
<ProductGroup>3000</ProductGroup>
<ProductNr>30006</ProductNr>
</Product>
<Product>
<Category>200</Category>
<ProductGroup>4000</ProductGroup>
<ProductNr>30007</ProductNr>
</Product>
<Product>
<Category>200</Category>
<ProductGroup>4000</ProductGroup>
<ProductNr>30009</ProductNr>
</Product>
</DataSet>