XSLT - проверить, равны ли два узла в цикле for-each - PullRequest
0 голосов
/ 25 сентября 2018

Это мой XML:

<Shipment>
<AddressData>   
    <Sender>
        <PartnerID>123</PartnerID>
        <Name1>Test</Name1>         
    </Sender>
    <Receiver>
        <PartnerID>124</PartnerID>
        <Name1>Test 2</Name1>       
    </Receiver>
</AddressData>
<Packaging>
    <Package>
        <ID>1</ID>
        <Length>20</Length>
        <Width>20</Width>           
        <PackageType>Carton</PackageType>
    </Package>
    <Package>
        <ID>2</ID>
        <Length>20</Length>
        <Width>20</Width>           
        <PackageType>Carton</PackageType>
    </Package>
</Packaging>
<Items>
    <Item>
        <PackageID>1</PackageID>
        <Partnumber>1234</Partnumber>
        <Quantity>3</Quantity>
    </Item>
    <Item>
        <PackageID>1</PackageID>
        <Partnumber>1235</Partnumber>
        <Quantity>3</Quantity>
    </Item>
    <Item>
        <PackageID>1</PackageID>
        <Partnumber>1236</Partnumber>
        <Quantity>3</Quantity>
    </Item>
    <Item>
        <PackageID>2</PackageID>
        <Partnumber>1232</Partnumber>
        <Quantity>3</Quantity>
    </Item>
    <Item>
        <PackageID>2</PackageID>
        <Partnumber>12322</Partnumber>
        <Quantity>3</Quantity>
    </Item>
</Items>

Я пытаюсь составить список соответствующих элементов каждого пакета непосредственно в поле Packaging XML.

Так что я будуполучить следующий результат:

<Shipment>
<AddressData>
    <Sender>
        <PartnerID>123</PartnerID>
        <Name1>Test</Name1>         
    </Sender>
    <Receiver>
        <PartnerID>124</PartnerID>
        <Name1>Test 2</Name1>       
    </Receiver>
</AddressData>
<Packaging>
    <Package>
        <ID>1</ID>
        <Length>20</Length>
        <Width>20</Width>           
        <PackageType>Carton</PackageType>
        <Items>
            <Item>
                <PackageID>1</PackageID>
                <Partnumber>1234</Partnumber>
                <Quantity>3</Quantity>
            </Item>
            <Item>
                <PackageID>1</PackageID>
                <Partnumber>1235</Partnumber>
                <Quantity>3</Quantity>
            </Item>
            <Item>
                <PackageID>1</PackageID>
                <Partnumber>1236</Partnumber>
                <Quantity>3</Quantity>
            </Item>
        </Items>
    </Package>
    <Package>
        <ID>2</ID>
        <Length>20</Length>
        <Width>20</Width>           
        <PackageType>Carton</PackageType>
        <Items>
            <Item>
                <PackageID>2</PackageID>
                <Partnumber>1232</Partnumber>
                <Quantity>3</Quantity>
            </Item>
            <Item>
                <PackageID>2</PackageID>
                <Partnumber>12322</Partnumber>
                <Quantity>3</Quantity>
            </Item>
        </Items>
    </Package>
</Packaging>

</Shipment>

Я попытался сделать следующее преобразование XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>
<xsl:template match="Items">
</xsl:template>

<xsl:template match="Packaging">
    <Packaging>
        <xsl:for-each select="Package">
            <ID>
                <xsl:value-of select="ID"/>
            </ID>
            <Length>
                <xsl:value-of select="Length"/>
            </Length>
            <Width>
                <xsl:value-of select="Width"/>
            </Width>
            <PackageType>
                <xsl:value-of select="PackageType"/>
            </PackageType>
            <Items>
                <xsl:for-each select="../../Items/Item">
                    <xsl:if test="PackageID = ../../Packaging/Package/ID">
                    <Item>
                        <PackageID><xsl:value-of select="PackageID"/></PackageID>
                        <Partnumber><xsl:value-of select="Partnumber"/></Partnumber>
                        <Quantity><xsl:value-of select="Quantity"/></Quantity>
                    </Item>
                    </xsl:if>
                </xsl:for-each>
            </Items>
        </xsl:for-each>
    </Packaging>
</xsl:template>
</xsl:stylesheet>

Мое текущее преобразование XSLT не работает, потому что все элементы независимо отID будет показан.Таким образом, оператор if, кажется, не работает правильно.

Спасибо

1 Ответ

0 голосов
/ 25 сентября 2018

Проблема в том, что как только вы делаете xsl:for-each select="../../Items/Item", вы попадаете в другой контекст, и ваш предыдущий контекст (пакета) фактически «забывается».

Что вы можете сделать, это сохранить текущий идентификатор пакета в переменной перед выбором элементов и использовать его в compate

<Items>
    <xsl:variable name="packageId" select="ID" />
    <xsl:for-each select="../../Items/Item">
        <xsl:if test="PackageID = $packageId">
        <Item>
            <PackageID><xsl:value-of select="PackageID"/></PackageID>
            <Partnumber><xsl:value-of select="Partnumber"/></Partnumber>
            <Quantity><xsl:value-of select="Quantity"/></Quantity>
        </Item>
        </xsl:if>
    </xsl:for-each>
</Items>

Фактически вы можете поместить свое условие в выборку.xsl:for-each вместо xsl:if

<xsl:variable name="packageId" select="ID" />
<xsl:for-each select="../../Items/Item[PackageID = $packageId]">

В этом случае это условие может ссылаться на текущий узел пакета, с current()

<xsl:for-each select="../../Items/Item[PackageID = current()/ID]">

Но сказавчто, может быть, даже лучше использовать xsl:key здесь.Определите ключ как этот (как ребенок xsl:stylesheet)

<xsl:key name="items" match="Item" use="PackageID" />

Тогда вы можете сделать это ...

<xsl:for-each select="key('items', ID)">

На самом деле, вам даже не нужноxsl:for-each здесь вообще.Используйте xsl:apply-templates и воспользуйтесь шаблоном идентификации.

Попробуйте этот упрощенный XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:key name="items" match="Item" use="PackageID" />

<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="Items" />

<xsl:template match="Package">
    <Package>
        <xsl:apply-templates />
        <Items>
          <xsl:apply-templates select="key('items', ID)" />
        </Items>
    </Package>
</xsl:template>
</xsl:stylesheet>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...