Группировка узлов XML от разных родителей - PullRequest
0 голосов
/ 07 марта 2011

Я разочарованно новичок в xslt и у меня есть вопрос, на который я просто не могу найти ответ.Я применяю преобразование к XML-файлу, а затем использую fo для вывода его в .pdf.Входной файл (xml) поступает из биллинговой системы, и мы хотим вывести его в формате PDF, который можно отправить клиентам по почте.Я использую xslt 1.0 и FOP генерирует PDF.У меня проблемы с группировкой узлов с одинаковыми именами (TAX) от 2 разных родителей (CHARGES и OTHER_CHARGES).Вот пример:
(Входной файл)

<BILL>
    <CHARGES PARENT_ID="123456" CUSTOMER="MR. JONES">
        <CHARGE NAME="CHARGE1" AMOUNT="10000">
            <TAXES>
                <TAX NAME="FEDERAL" AMOUNT="200"/>
                <TAX NAME="STATE" AMOUNT="50">
            </TAXES>
        </CHARGE>
    </CHARGES>
    <OTHER_CHARGES PARENT_ID="123456" CUSTOMER="MR_JONES">
        <OTHER_CHARGE NAME="OTHER_CHARGE1">
            <TAXES>
                <TAX NAME="FEDERAL" AMOUNT="150"/>
            </TAXES>
        </OTHER_CHARGE>
    </OTHER_CHARGES>
</BILL>

Я хочу, чтобы общие налоги на выставленные товары были такими, чтобы вывод в формате PDF выглядел примерно так

НАЛОГИ

ФЕДЕРАЛЬНЫЙ - $ 350
СОСТОЯНИЕ - $ 50

С общими налогами, сгруппированными по названию с их итогами, несмотря на то, что они поступают из разных узлов.У меня ограниченное понимание ключей и группировки, но я не могу найти тот магический пример, который щелкает переключателем в моем мозгу.

Ответы [ 3 ]

1 голос
/ 07 марта 2011
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:strip-space elements="*"/>
    <xsl:key name="kTaxes" match="TAX" use="@NAME"/>
    <xsl:template match="/*">
        <xsl:apply-templates select="
            */*/TAXES/TAX[generate-id() = generate-id(key('kTaxes', @NAME)[1])]
            "/>
    </xsl:template>
    <xsl:template match="TAX">
        <xsl:value-of select="@NAME"/>
        <xsl:text>: </xsl:text>
        <xsl:value-of select="sum(key('kTaxes', @NAME)/@AMOUNT)"/>
        <xsl:text>&#xa;</xsl:text>
    </xsl:template>
</xsl:stylesheet>

Применительно к чуть более сложному документу:

<BILL>
    <CHARGES PARENT_ID="123456" CUSTOMER="MR. JONES">
        <CHARGE NAME="CHARGE1" AMOUNT="10000">
            <TAXES>
                <TAX NAME="FEDERAL" AMOUNT="200"/>
                <TAX NAME="STATE" AMOUNT="50"/>
                <TAX NAME="HEALTH" AMOUNT="300"/>
            </TAXES>
        </CHARGE>   
    </CHARGES>
    <OTHER_CHARGES PARENT_ID="123456" CUSTOMER="MR_JONES">
        <OTHER_CHARGE NAME="OTHER_CHARGE1">
            <TAXES>
                <TAX NAME="FEDERAL" AMOUNT="150"/>
                <TAX NAME="MATERNITY" AMOUNT="150"/>
                <TAX NAME="HEALTH" AMOUNT="600"/>
            </TAXES>
        </OTHER_CHARGE>
    </OTHER_CHARGES>
</BILL>

Правильный результат будет:

FEDERAL: 350
STATE: 50
HEALTH: 900
MATERNITY: 150
1 голос
/ 07 марта 2011

Итак, что вы могли бы сделать (если вам нужно придерживаться XSLT 1.0):

  • Выбрать все налоги в переменной

<xs:variable name="taxes" select="//TAX"/>

  • Затем выберите отдельные имена НАЛОГОВ, как это:

<xs:variable name="distict_taxes" select="//$taxes[not(@NAME=preceding::TAX/@NAME)"/>

  • Затем выполните итерацию по этим отдельным налогам, введя имя для каждого впеременная $ taxname и do:

<xs:value-of select="sum(//*/TAXES/TAX[@NAME=$taxname]/@AMOUNT)"/>

Надеюсь, это поможет.

0 голосов
/ 07 марта 2011

Если вы можете использовать XSLT 2.0, попробуйте следующее:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="2.0">

    <xsl:output method="xml" indent="yes" omit-xml-declaration="no" />

    <xsl:template match="BILL">
        <report>
            <xsl:for-each-group select=".//TAX" group-by="@NAME">
                <tax>
                    <xsl:attribute name="name">
                        <xsl:value-of
                            select="current-grouping-key()" />
                    </xsl:attribute>
                    <xsl:attribute name="total">
                        <xsl:value-of 
                            select="sum(current-group()/@AMOUNT)" />
                    </xsl:attribute>
                </tax>
            </xsl:for-each-group>
        </report>
    </xsl:template>

</xsl:stylesheet>

Вывод

<report>
    <tax name="FEDERAL" total="350"/>
    <tax name="STATE" total="50"/>
</report>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...