如何在以下情况下使用XSLT 而不使用xsl:for-each-group
我的要求:如果Field1 ..迭代的Field6匹配组中任何迭代的Field1 .. Field6,那么我们需要对数量求和并获取该组的最低ID。
的输入 的
<Shipment>
<ID>1</ID>
<Field1>abcd</Field1>
<Field2>1234</Field2>
<Field3>efgh</Field4>
<Field4>5678</Field4>
<Field5>ijkl</Field5>
<Field6>90mn</Field6>
<Amount>200.00</Amount>
</Shipment>
<Shipment>
<ID>2</ID>
<Field1>abcd</Field1>
<Field2>1234</Field2>
<Field3>efgh</Field4>
<Field4>5678</Field4>
<Field5>ijkl</Field5>
<Field6>90mn</Field6>
<Amount>600.00</Amount>
</Shipment>
<Shipment>
<ID>3</ID>
<Field1>1234</Field1>
<Field2>abcd</Field2>
<Field3>efgh</Field4>
<Field4>5678</Field4>
<Field5>2345</Field5>
<Field6>80mn</Field6>
<Amount>600.00</Amount>
</Shipment>
预期的OutPut
<Shipment>
<ID>1</ID>
<Field1>abcd</Field1>
<Field2>1234</Field2>
<Field3>efgh</Field4>
<Field4>5678</Field4>
<Field5>ijkl</Field5>
<Field6>90mn</Field6>
<Amount>800.00</Amount>
</Shipment>
<Shipment>
<ID>2</ID>
<Field1>1234</Field1>
<Field2>abcd</Field2>
<Field3>efgh</Field4>
<Field4>5678</Field4>
<Field5>2345</Field5>
<Field6>80mn</Field6>
<Amount>600.00</Amount>
</Shipment>
答案 0 :(得分:1)
不使用xsl:for-each-group
的要求明确表明XSLT 2.0处理器不可用。
这是一个XSLT 1.0解决方案:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kAllFields" match="Shipment" use=
"concat(Field1,'+',Field2,'+',Field3,'+',Field4,'+',Field5,'+',Field6)"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"Shipment
[not(generate-id()
=
generate-id(key('kAllFields',
concat(Field1,'+',Field2,'+',Field3,'+',Field4,'+',Field5,'+',Field6))[1]))]
"/>
<xsl:template match="Shipment">
<xsl:variable name="vGroup" select=
"key('kAllFields', concat(Field1,'+',Field2,'+',Field3,'+',Field4,'+',Field5,'+',Field6))"/>
<Shipment>
<ID>
<xsl:call-template name="min">
<xsl:with-param name="pItems" select="$vGroup/ID"/>
</xsl:call-template>
</ID>
<xsl:apply-templates select="*[starts-with(name(), 'Field')]"/>
<Amount><xsl:value-of select="sum($vGroup/Amount)"/></Amount>
</Shipment>
</xsl:template>
<xsl:template name="min">
<xsl:param name="pItems" select="/.."/>
<xsl:param name="pDataType" select="'number'"/>
<xsl:for-each select="$pItems">
<xsl:sort data-type="{$pDataType}"/>
<xsl:if test="position() =1"><xsl:value-of select="."/></xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
将此转换应用于以下XML文档(提供的严重格式错误的片段 - 更正并包装到单个顶部元素中以使其成为格式良好的XML文档):
<t>
<Shipment>
<ID>1</ID>
<Field1>abcd</Field1>
<Field2>1234</Field2>
<Field3>efgh</Field3>
<Field4>5678</Field4>
<Field5>ijkl</Field5>
<Field6>90mn</Field6>
<Amount>200.00</Amount>
</Shipment>
<Shipment>
<ID>2</ID>
<Field1>abcd</Field1>
<Field2>1234</Field2>
<Field3>efgh</Field3>
<Field4>5678</Field4>
<Field5>ijkl</Field5>
<Field6>90mn</Field6>
<Amount>600.00</Amount>
</Shipment>
<Shipment>
<ID>3</ID>
<Field1>1234</Field1>
<Field2>abcd</Field2>
<Field3>efgh</Field3>
<Field4>5678</Field4>
<Field5>2345</Field5>
<Field6>80mn</Field6>
<Amount>600.00</Amount>
</Shipment>
</t>
产生了想要的正确结果:
<t>
<Shipment>
<ID>1</ID>
<Field1>abcd</Field1>
<Field2>1234</Field2>
<Field3>efgh</Field3>
<Field4>5678</Field4>
<Field5>ijkl</Field5>
<Field6>90mn</Field6>
<Amount>800</Amount>
</Shipment>
<Shipment>
<ID>3</ID>
<Field1>1234</Field1>
<Field2>abcd</Field2>
<Field3>efgh</Field3>
<Field4>5678</Field4>
<Field5>2345</Field5>
<Field6>80mn</Field6>
<Amount>600</Amount>
</Shipment>
</t>
答案 1 :(得分:0)
您需要选择在Field1到Field6中未使用的分隔符。
<xsl:param name="separator" select="'-'"/>
<xsl:template match="/shipments">
<xsl:for-each-group select="Shipment" group-by="concat(Field1,$separator,Field2,$separator,Field3,$separator,Field4,$separator,Field5,$separator,Field6)">
<xsl:copy-of select="current-group()[ID=min(current-group()/ID)]"/>
</xsl:for-each-group>
</xsl:template>