Как преобразовать этот XML с помощью XSLT (проблема внутреннего цикла)? - PullRequest
1 голос
/ 06 мая 2019

У меня есть определенная структура вывода XML, которая не соответствует моим требованиям. По этой причине я рассматриваю возможность использования кода XSLT для преобразования текущей структуры в требуемую.

Я понимаю, что мне нужна переменная XSLT, а также условие if для завершения желаемого результата.

Это мой текущий ввод XML:

<ShipmentInstruction>
        <CarrierCode>AFH</CarrierCode>
        <CarrierProductCode>AFH</CarrierProductCode>
        <ShipmentNoOfBoxes>2</ShipmentNoOfBoxes>
        <Boxes>
          <Box>
            <ShipmentBoxNr>0000000011</ShipmentBoxNr>
            <ShipmentBoxReference>0000000011</ShipmentBoxReference>
            <ShipmentBoxWeight>1.5</ShipmentBoxWeight>
            <Contents>
              <Content>
                <BarCode>8719829088824</BarCode>
              </Content>
            </Contents>
          </Box>
          <Box>
            <ShipmentBoxNr>0000000011</ShipmentBoxNr>
            <ShipmentBoxReference>0000000011</ShipmentBoxReference>
            <ShipmentBoxWeight>1.5</ShipmentBoxWeight>
            <Contents>
              <Content>
                <BarCode>8719829088831</BarCode>
              </Content>
            </Contents>
          </Box>
          <Box>
            <ShipmentBoxNr>0000000011</ShipmentBoxNr>
            <ShipmentBoxReference>0000000011</ShipmentBoxReference>
            <ShipmentBoxWeight>1.5</ShipmentBoxWeight>
            <Contents>
              <Content>
                <BarCode>8719829088848</BarCode>
              </Content>
            </Contents>
          </Box>
          <Box>
            <ShipmentBoxNr>0000000022</ShipmentBoxNr>
            <ShipmentBoxReference>0000000022</ShipmentBoxReference>
            <ShipmentBoxWeight>7.5</ShipmentBoxWeight>
            <Contents>
              <Content>
                <BarCode>8719829088572</BarCode>
              </Content>
            </Contents>
          </Box>
          <Box>
            <ShipmentBoxNr>0000000022</ShipmentBoxNr>
            <ShipmentBoxReference>0000000022</ShipmentBoxReference>
            <ShipmentBoxWeight>7.5</ShipmentBoxWeight>
            <Contents>
              <Content>
                <BarCode>8719829088589</BarCode>
              </Content>
            </Contents>
          </Box>
        </Boxes>
</ShipmentInstruction>

И это мой требуемый вывод:

<ShipmentInstruction>
        <CarrierCode>AFH</CarrierCode>
        <CarrierProductCode>AFH</CarrierProductCode>
        <ShipmentNoOfBoxes>2</ShipmentNoOfBoxes>
        <Boxes>
          <Box>
            <ShipmentBoxNr>0000000011</ShipmentBoxNr>
            <ShipmentBoxReference>0000000011</ShipmentBoxReference>
            <ShipmentBoxWeight>1.5</ShipmentBoxWeight>
            <Contents>
              <Content>
                <BarCode>8719829088824</BarCode>
              </Content>
              <Content>
                <BarCode>8719829088831</BarCode>
              </Content>
              <Content>
                <BarCode>8719829088848</BarCode>
              </Content>
            </Contents>
          </Box>
          <Box>
            <ShipmentBoxNr>0000000022</ShipmentBoxNr>
            <ShipmentBoxReference>0000000022</ShipmentBoxReference>
            <ShipmentBoxWeight>7.5</ShipmentBoxWeight>
            <Contents>
              <Content>
                <BarCode>8719829088572</BarCode>
              </Content>
              <Content>
                <BarCode>8719829088589</BarCode>
              </Content>
            </Contents>
          </Box>
        </Boxes>
      </ShipmentInstruction>

XSLT, который я использовал до тех пор, пока не появится:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

    <xsl:template match="/">
                <xsl:element name="ShipmentInstruction">
                        <xsl:element name="CarrierCode">
                            <xsl:value-of select="//ShipmentInstruction/CarrierCode"/> 
                        </xsl:element>
                        <xsl:element name="CarrierProductCode">
                            <xsl:value-of select="//ShipmentInstruction/CarrierProductCode"/> 
                        </xsl:element>
                        <xsl:element name="ShipmentNoOfBoxes">
                            <xsl:value-of select="//ShipmentInstruction/ShipmentNoOfBoxes"/> 
                        </xsl:element>
                        <xsl:element name="Boxes">
                            <xsl:for-each select="//ShipmentInstruction/Boxes/Box">
                            <xsl:variable name="v1" select="ShipmentBoxNr"/>
                             <xsl:element name="Box">
                             <xsl:variable name="v2" select="ShipmentBoxNr"/>
                                <xsl:element name="ShipmentBoxNr">
                                    <xsl:value-of select="ShipmentBoxNr"/> 
                                </xsl:element>
                                <xsl:element name="ShipmentBoxReference">
                                    <xsl:value-of select="ShipmentBoxReference"/> 
                                </xsl:element>
                                <xsl:element name="ShipmentBoxWeight">
                                    <xsl:value-of select="ShipmentBoxWeight"/> 
                                </xsl:element>
                                    <xsl:element name="Contents">   
                                    <xsl:for-each select="//Contents/Content">
                                        <xsl:element name="Content">
                                            <xsl:element name="Barcode">
                                                <xsl:value-of select="Barcode"/> 
                                            </xsl:element>
                                        </xsl:element>
                                    </xsl:for-each>
                                    </xsl:element>                              
                             </xsl:element>
                            </xsl:for-each>
                        </xsl:element>
                </xsl:element>
    </xsl:template>
</xsl:stylesheet>

Ответы [ 2 ]

1 голос
/ 06 мая 2019

Или просто:

XSLT 2.0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

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

<xsl:template match="Boxes">
    <xsl:copy>
        <xsl:for-each-group select="Box" group-by="ShipmentBoxNr">
            <Box>
                <xsl:copy-of select="* except Contents"/>
                <Contents>
                    <xsl:copy-of select="current-group()/Contents/Content"/>
                </Contents>
            </Box>
        </xsl:for-each-group>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>
1 голос
/ 06 мая 2019

Кажется, вы используете XSLT 2.0, вы можете использовать for-each-group для группировки элемента <Content> на основе ShipmentBoxNr

Попробуйте это:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">

<xsl:output method="xml" indent="yes" />
<xsl:strip-space elements="*" />

<xsl:template match="/">
    <xsl:element name="ShipmentInstruction">
        <xsl:element name="CarrierCode">
            <xsl:value-of select="//ShipmentInstruction/CarrierCode" />
        </xsl:element>
        <xsl:element name="CarrierProductCode">
            <xsl:value-of select="//ShipmentInstruction/CarrierProductCode" />
        </xsl:element>
        <xsl:element name="ShipmentNoOfBoxes">
            <xsl:value-of select="//ShipmentInstruction/ShipmentNoOfBoxes" />
        </xsl:element>
        <xsl:element name="Boxes">
            <xsl:for-each-group select="ShipmentInstruction/Boxes/Box"
                group-by="ShipmentBoxNr">

                <xsl:element name="Box">
                    <xsl:element name="ShipmentBoxNr">
                        <xsl:value-of select="ShipmentBoxNr" />
                    </xsl:element>
                    <xsl:element name="ShipmentBoxReference">
                        <xsl:value-of select="ShipmentBoxReference" />
                    </xsl:element>
                    <xsl:element name="ShipmentBoxWeight">
                        <xsl:value-of select="ShipmentBoxWeight" />
                    </xsl:element>
                    <xsl:element name="Contents">
                        <xsl:for-each-group select="current-group()/Contents/Content" group-starting-with="BarCode">
                            <xsl:copy-of select="current-group()" />
                        </xsl:for-each-group>
                    </xsl:element>
                </xsl:element>
            </xsl:for-each-group>
        </xsl:element>
    </xsl:element>
</xsl:template>
</xsl:stylesheet>

См. Демо здесь: https://xsltfiddle.liberty -development.net / 6r5Gh3v

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...