Как вернуть одно значение, если дубликат приводит к переменной XSLT? - PullRequest
0 голосов
/ 21 июня 2019

Использование 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>

В настоящее время это мой код, который не работает. У меня есть два шаблона ...

  • Один изолирует входные сегменты, которые имеют уникальные «Описания», и выводит их индивидуально (эта часть работает).

  • Другой (неудачный) - это то, где я пытаюсь свернуть / объединить ввод соответствующего «Описание»; и выведите их идентичные значения подкатегории («H340»), Description («налог EPA»), «C» и суммируйте значение («2.86» и «20.00»).

Примечание: для суммы части 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>

1 Ответ

1 голос
/ 25 июня 2019

Можно использовать xsl: key и generate-id () для выбора уникальной группировки результатов по составным ключам.

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