在 XSLT 变量中出现重复结果时如何 return 单个值?

How to return single value when duplicate results in XSLT variable?

使用 XSLT 1.0 (Xalan)-

从这段输入XML...

        <LineComponent>
            <Adjustment Type="Addition" Category="Premium" SubCategory="D240">
                <Description>Freight</Description>
                <Value>10.00</Value>
            </Adjustment>
        </LineComponent>
        <LineComponent>
            <Adjustment Type="Deduction" Category="Discount" SubCategory="D240">
                <Description>Freight Discount</Description>
                <Value>-55.00</Value>
            </Adjustment>
        </LineComponent>
        <LineComponent>
            <Adjustment Type="Addition" Category="Premium" SubCategory="H340">
                <Description>EPA Tax</Description>
                <Value>2.86</Value>
            </Adjustment>
        </LineComponent>
        <LineComponent>
            <Adjustment Type="Addition" Category="Premium" SubCategory="H340">
                <Description>EPA Tax</Description>
                <Value>20.00</Value>
            </Adjustment>
        </LineComponent>

我需要输出...

<Segment id="SAC">
    <Record id="SAC">
        <Field id="248">C</Field>
        <Field id="1300">D240</Field>
        <Field id="610">1000</Field>
        <Field id="331">06</Field>
        <Field id="352">Freight</Field>
    </Record>
</Segment>
<Segment id="SAC">
    <Record id="SAC">
        <Field id="248">A</Field>
        <Field id="1300">D240</Field>
        <Field id="610">5500</Field>
        <Field id="331">06</Field>
        <Field id="352">Freight Discount</Field>
    </Record>
</Segment>
<Segment id="SAC">
    <Record id="SAC">
        <Field id="248">C</Field>
        <Field id="1300">H340</Field>
        <Field id="610">2286</Field>
        <Field id="331">06</Field>
        <Field id="352">EPA Tax</Field>
    </Record>
</Segment>

...但我得到的输出不正确(注意值的串联)...

<Segment id="SAC">
    <Record id="SAC">
        <Field id="248">C</Field>
        <Field id="1300">D240</Field>
        <Field id="610">1000</Field>
        <Field id="331">06</Field>
        <Field id="352">Freight</Field>
    </Record>
</Segment>
<Segment id="SAC">
    <Record id="SAC">
        <Field id="248">A</Field>
        <Field id="1300">D240</Field>
        <Field id="610">5500</Field>
        <Field id="331">06</Field>
        <Field id="352">Freight Discount</Field>
    </Record>
</Segment>
<Segment id="SAC">
    <Record id="SAC">
        <Field id="248">CC</Field>
        <Field id="1300">H340H340</Field>
        <Field id="610">2862000</Field>
        <Field id="331">06</Field>
        <Field id="352">EPA TaxEPATax</Field>
    </Record>
</Segment>

这是我目前无法使用的代码。我有两个模板...

注意:对于 Value 部分的总和,我去掉了小数点(因此 2.86 + 20.00 = 22.86 在最终输出中变为 2286。)

    <xsl:template name="SAC">
    <!-- Service, Promotion, Allowance, or Charge Information -->
    <!-- Output Unique Descriptions Part-->
    <xsl:for-each
        select="
            //LineComponent/Adjustment[@SubCategory]/Description[not(. = preceding::LineComponent/Adjustment[@SubCategory]/Description)
            and not(. = following::LineComponent/Adjustment[@SubCategory]/Description)]">
        <Segment id="SAC">
            <!-- Service, Promotion, Allowance, or Charge Information -->
            <Record id="SAC">
                <!-- Allowance or Charge Indicator -->
                <Field id="248">
                    <xsl:choose>
                        <xsl:when test="../@Type = 'Addition'">
                            <!-- 'C' = Charge -->
                            <xsl:text>C</xsl:text>
                        </xsl:when>
                        <xsl:when test="../@Type = 'Deduction'">
                            <!-- 'A' = Allowance -->
                            <xsl:text>A</xsl:text>
                        </xsl:when>
                        <xsl:otherwise/>
                    </xsl:choose>
                </Field>
                <!-- Service, Promotion, Allowance, or Charge Code (Including Taxes) -->
                <Field id="1300">
                    <xsl:value-of select="../@SubCategory"/>
                </Field>
                <!--  Amount  -->
                <Field id="610">
                    <xsl:value-of select="translate(../Value, '.-+', '')"/>
                </Field>
                <!--  Allowance/Charge Percent Qualifier  -->
                <!--<Field id="378">
                <!-\- Hard-Coded value 'Z' = Mutually Defined -\->
                <xsl:text>Z</xsl:text>
            </Field>-->
                <!--  Allowance or Charge Method of Handling Code  -->
                <Field id="331">
                    <!-- Hard-Coded value '06' = Charge to be Paid by Customer -->
                    <xsl:text>06</xsl:text>
                </Field>
                <!-- Description -->
                <Field id="352">
                    <xsl:value-of select="../Description"/>
                </Field>
            </Record>
        </Segment>
    </xsl:for-each>
    <!-- Combine Common Descriptions Part-->
    <xsl:variable name="ACIndicator">
        <xsl:for-each
            select="
                //LineComponent/Adjustment[@SubCategory]/Description[(. = preceding::LineComponent/Adjustment[@SubCategory]/Description)
                or (. = following::LineComponent/Adjustment[@SubCategory]/Description)]">
            <xsl:choose>
                <xsl:when test="../@Type = 'Addition'">
                    <!-- 'C' = Charge -->
                    <xsl:text>C</xsl:text>
                </xsl:when>
                <xsl:when test="../@Type = 'Deduction'">
                    <!-- 'A' = Allowance -->
                    <xsl:text>A</xsl:text>
                </xsl:when>
                <xsl:otherwise/>
            </xsl:choose>
        </xsl:for-each>
    </xsl:variable>
    <xsl:variable name="ACSubCategory">
        <xsl:for-each
            select="
                //LineComponent/Adjustment[@SubCategory]/Description[(. = preceding::LineComponent/Adjustment[@SubCategory]/Description)
                or (. = following::LineComponent/Adjustment[@SubCategory]/Description)]">
            <xsl:value-of select="../@SubCategory"/>
        </xsl:for-each>
    </xsl:variable>
    <xsl:variable name="ACTotalValue">
        <xsl:for-each
            select="
                //LineComponent/Adjustment[@SubCategory]/Description[(. = preceding::LineComponent/Adjustment[@SubCategory]/Description)
                or (. = following::LineComponent/Adjustment[@SubCategory]/Description)]">
            <xsl:value-of select="../Value"/>
        </xsl:for-each>
    </xsl:variable>
    <xsl:variable name="ACDescription">
        <xsl:for-each
            select="
                //LineComponent/Adjustment[@SubCategory]/Description[(. = preceding::LineComponent/Adjustment[@SubCategory]/Description)
                or (. = following::LineComponent/Adjustment[@SubCategory]/Description)]">
            <xsl:value-of
                select="."
            />
        </xsl:for-each>
    </xsl:variable>
    <Segment id="SAC">
        <!-- Service, Promotion, Allowance, or Charge Information -->
        <Record id="SAC">
            <!-- Allowance or Charge Indicator -->
            <Field id="248">
                <xsl:value-of
                    select="$ACIndicator"
                />
            </Field>
            <!-- Service, Promotion, Allowance, or Charge Code (Including Taxes) -->
            <Field id="1300">
                <xsl:value-of select="$ACSubCategory"/>
            </Field>
            <!--  Amount  -->
            <Field id="610">
                <xsl:value-of select="translate($ACTotalValue, '.-+', '')"/>
            </Field>
            <!--  Allowance or Charge Method of Handling Code  -->
            <Field id="331">
                <!-- Hard-Coded value '06' = Charge to be Paid by Customer -->
                <xsl:text>06</xsl:text>
            </Field>
            <!-- Description -->
            <Field id="352">
                <xsl:value-of select="$ACDescription"/>
            </Field>
        </Record>
    </Segment>
</xsl:template>

可以使用 xsl:key 和 generate-id() 来 select 通过复合键进行唯一结果分组。

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="adjustmentDistinct" match="Adjustment" use="concat(@Type, '+', @Category, '+', @SubCategory)"/>
<xsl:template name="SAC" match="/"> 
    <xsl:for-each select=
     "//Adjustment[generate-id()
          =
           generate-id(key('adjustmentDistinct',
                           concat(@Type, '+', @Category, '+', @SubCategory)
                           )[1]
                       )
           ]
    ">
        <xsl:variable name="vkeyGroup" select=
        "key('adjustmentDistinct', concat(@Type, '+', @Category, '+', @SubCategory))"/>
        <Segment id="SAC">
            <!-- Service, Promotion, Allowance, or Charge Information -->
            <Record id="SAC">
                <!-- Allowance or Charge Indicator -->
                <Field id="248">
                    <xsl:choose>
                        <xsl:when test="@Type = 'Addition'">
                            <!-- 'C' = Charge -->
                            C
                        </xsl:when>
                        <xsl:when test="@Type = 'Deduction'">
                            <!-- 'A' = Allowance -->
                            A
                        </xsl:when>
                        <xsl:otherwise/>
                    </xsl:choose>
                </Field>
                <!-- Service, Promotion, Allowance, or Charge Code (Including Taxes) -->
                <Field id="1300">
                    <xsl:value-of select="@SubCategory"/>
                </Field>
                <!--  Amount  -->
                <Field id="610">
                    <xsl:variable name="vSum" select="format-number(sum($vkeyGroup/Value), '#.00')" />
                    <xsl:value-of select="translate($vSum, '.-+', '')"/>
                </Field>
                <!--  Allowance or Charge Method of Handling Code  -->
                <Field id="331">
                    <!-- Hard-Coded value '06' = Charge to be Paid by Customer -->
                    <xsl:text>06</xsl:text>
                </Field>
                <!-- Description -->
                <Field id="352">
                    <xsl:value-of select="Description"/>
                </Field>
            </Record>
        </Segment>
    </xsl:for-each>

</xsl:template>

</xsl:stylesheet>