2

如何在不使用的情况下将 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>

预期产出

<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>
4

2 回答 2

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>
于 2013-03-28T01:58:41.787 回答
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>

工作示例

于 2013-03-27T22:56:59.077 回答