XSL基于与兄弟值的部分匹配来选择和求和节点

时间:2017-11-17 19:54:14

标签: xml xslt xpath

我们来自Oracle报告的XML格式不佳。该报告包含数千个订单。每个订单包含不到一千行。每行包含许多费用。我们使用XSL模板读取XML以进行清理。我在阅读费用部分时遇到问题,并按订单汇总每种费用类型。

查看下面的示例,我们有Ack_Line__Hdr_S32包含费用。 AckLine_ID2是行号。调用模板时,我们有订单号,但订单号不包含行号。这意味着,我们的订货号为'0705181439',并且必须根据行编号0705181439009的前十个字符对其进行评估。

下面的第一个XSL解决方案一直有效,直到订单量增长。现在它在一段时间后崩溃了。源XML文件大约为50MB。

以下是详细信息:

示例XML:

<Charges_and_Fees_S9_Group>
  <Ack_Line___Hdr_S32>
    <AckLine_ID2>0705181439009</AckLine_ID2>
    <On_2nd_Item_Number_S19>
      <ChargeItemNumber_ID1>ACCESSCH                 </ChargeItemNumber_ID1>
      <ChargesAndFees_ID3>30.00</ChargesAndFees_ID3>
      <ChargeItemDescription_ID4>Accessorial Charge</ChargeItemDescription_ID4>
    </On_2nd_Item_Number_S19>
    <On_2nd_Item_Number_S19>
      <ChargeItemNumber_ID1>FLANDED                  </ChargeItemNumber_ID1>
      <ChargesAndFees_ID3>67.12</ChargesAndFees_ID3>
      <ChargeItemDescription_ID4>Freight - Landed Freight</ChargeItemDescription_ID4>
    </On_2nd_Item_Number_S19>
    <On_2nd_Item_Number_S19>
      <ChargeItemNumber_ID1>FUELSURG                 </ChargeItemNumber_ID1>
      <ChargesAndFees_ID3>27.12</ChargesAndFees_ID3>
      <ChargeItemDescription_ID4>Fuel Surcharge</ChargeItemDescription_ID4>
    </On_2nd_Item_Number_S19>
    <AckLine_Freight_ID1>67.12</AckLine_Freight_ID1>
    <AckLine_ChargesAndFees_ID2>57.12</AckLine_ChargesAndFees_ID2>
    <AckLine_FuelSurcharge_ID4>27.12</AckLine_FuelSurcharge_ID4>
    <AckLine_AccessorialSurcharge_ID6>30.00</AckLine_AccessorialSurcharge_ID6>
  </Ack_Line___Hdr_S32>
</Charges_and_Fees_S9_Group>
<Charges_and_Fees_S9_Group>
  <Ack_Line___Hdr_S32>
    <AckLine_ID2>0705181439010</AckLine_ID2>
    <On_2nd_Item_Number_S19>
      <ChargeItemNumber_ID1>ACCESSCH                 </ChargeItemNumber_ID1>
      <ChargesAndFees_ID3>30.00</ChargesAndFees_ID3>
      <ChargeItemDescription_ID4>Accessorial Charge</ChargeItemDescription_ID4>
    </On_2nd_Item_Number_S19>
    <On_2nd_Item_Number_S19>
      <ChargeItemNumber_ID1>FLANDED                  </ChargeItemNumber_ID1>
      <ChargesAndFees_ID3>67.12</ChargesAndFees_ID3>
      <ChargeItemDescription_ID4>Freight - Landed Freight</ChargeItemDescription_ID4>
    </On_2nd_Item_Number_S19>
    <On_2nd_Item_Number_S19>
      <ChargeItemNumber_ID1>FUELSURG                 </ChargeItemNumber_ID1>
      <ChargesAndFees_ID3>27.12</ChargesAndFees_ID3>
      <ChargeItemDescription_ID4>Fuel Surcharge</ChargeItemDescription_ID4>
    </On_2nd_Item_Number_S19>
    <AckLine_Freight_ID1>67.12</AckLine_Freight_ID1>
    <AckLine_ChargesAndFees_ID2>57.12</AckLine_ChargesAndFees_ID2>
    <AckLine_FuelSurcharge_ID4>27.12</AckLine_FuelSurcharge_ID4>
    <AckLine_AccessorialSurcharge_ID6>30.00</AckLine_AccessorialSurcharge_ID6>
  </Ack_Line___Hdr_S32>
</Charges_and_Fees_S9_Group>

旧XSL模板:

<xsl:template name="ChargesTotal">
  <xsl:param name="AckLineNumber" />
    <Total_Accessorial>
      <xsl:if test="//AckLine_AccessorialSurcharge_ID6  [substring(../AckLine_ID2, 1, 10)=$AckLineNumber]" >
        <xsl:value-of select="format-number(sum(//AckLine_AccessorialSurcharge_ID6  [substring(../AckLine_ID2, 1, 10)=$AckLineNumber]), '#.00')" />
      </xsl:if>
    </Total_Accessorial>  
</xsl:template>

新XSL模板:

<xsl:template name="ChargesTotal">
  <xsl:param name="AckLineNumber" />
  <xsl:variable name="setSurchargeAcc" select="Ack_Line___Hdr_S32/AckLine_AccessorialSurcharge_ID6[substring(../AckLine_ID2, 1, 10)=$AckLineNumber]"/>
  <Total_Accessorial>
    <xsl:value-of select="format-number(sum($setSurchargeAcc/AckLine_AccessorialSurcharge_ID6), '#.00')" />
  </Total_Accessorial>
</xsl:template>

预期产出:

<Total_Accessorial>60.00</Total_Accessorial>

1 个答案:

答案 0 :(得分:0)

您可以尝试定义一个键

<xsl:key name="line-id" match="Charges_and_Fees_S9_Group/Ack_Line___Hdr_S32"
  use="substring(AckLine_ID2, 1, 10)"/>

那么你可以这样做。

<xsl:variable name="setSurchargeAcc" select="key('line-id', $AckLineNumber)"/>

<Total_Accessorial>
  <xsl:if test="$setSurchargeAcc">
    <xsl:value-of select="format-number(sum($setSurchargeAcc/AckLine_AccessorialSurcharge_ID6), '#.00')" />
  </xsl:if>
</Total_Accessorial>