سؤال

I have a complex XML that has a header section and multiple item sections. The XML is as follows:

<Order>
<OrderNumber>A</OrderNumber>
<SubTotal>20.00</SubTotal>
<Tax>
    <TaxCode>AA</TaxCode>
    <TaxAmount>1.00</TaxAmount>
</Tax>
<TotalAmount>21.00</TotalAmount>
<ItemSection>
    <SectionNumber>1</SectionNumber>
    <Item>
        <Product>
            <LineNumber>10</LineNumber>
            <IsConfig>Y</IsConfig>
            <Config>
                <Product>
                    <LineNumber>10-1</LineNumber>
                    <IsConfig>Y</IsConfig>
                    <Config>
                        <Product>
                            <LineNumber>10-1-1</LineNumber>
                            <IsConfig>N</IsConfig>
                            <LineTotal>2.00</LineTotal>
                        </Product>
                        <Product>
                            <LineNumber>10-1-2</LineNumber>
                            <IsConfig>N</IsConfig>
                            <LineTotal>1.00</LineTotal>
                        </Product>
                    </Config>
                    <LineITotal>1.00</LineITotal>
                </Product>
                <Product>
                    <LineNumber>10-2</LineNumber>
                    <IsConfig>N</IsConfig>
                    <LineITotal>4.00</LineITotal>
                </Product>
            </Config>
            <LineITotal>1.00</LineITotal>
        </Product>
    </Item>
    <Item>
        <Product>
            <LineNumber>20</LineNumber>
            <IsConfig>N</IsConfig>
            <LineITotal>1.00</LineITotal>
        </Product>
    </Item>
</ItemSection>
<ItemSection>
    <SectionNumber>2</SectionNumber>
    <Item>
        <Product>
            <LineNumber>30</LineNumber>
            <IsConfig>Y</IsConfig>
            <Config>
                <Product>
                    <LineNumber>30-1</LineNumber>
                    <IsConfig>Y</IsConfig>
                    <Config>
                        <Product>
                            <LineNumber>30-1-1</LineNumber>
                            <IsConfig>N</IsConfig>
                            <LineTotal>2.00</LineTotal>
                        </Product>
                        <Product>
                            <LineNumber>30-1-2</LineNumber>
                            <IsConfig>N</IsConfig>
                            <LineTotal>1.00</LineTotal>
                        </Product>
                    </Config>
                    <LineITotal>1.00</LineITotal>
                </Product>
                <Product>
                    <LineNumber>30-2</LineNumber>
                    <IsConfig>N</IsConfig>
                    <LineITotal>4.00</LineITotal>
                </Product>
            </Config>
            <LineITotal>1.00</LineITotal>
        </Product>
    </Item>
    <Item>
        <Product>
            <LineNumber>40</LineNumber>
            <IsConfig>N</IsConfig>
            <LineITotal>1.00</LineITotal>
        </Product>
    </Item>
</ItemSection>

I need to flatten the structure and move all the Product blocks, regardless of what level they appear at and move them to the same level as Item/Product as follows. While doing this, I need to change the value of IsConfig to N and remove the Config element that surrounds the Product. At the same time, I need to copy all the elements above ItemSection. Note there can be N levels for Config/Product blocks. The result should be like this:

<Order>
<OrderNumber>A</OrderNumber>
<SubTotal>10.00</SubTotal>
<Tax>
    <TaxCode>AA</TaxCode>
    <TaxAmount>1.00</TaxAmount>
</Tax>
<TotalAmount>21.00</TotalAmount>
<ItemSection>
    <SectionNumber>1</SectionNumber>
    <Item>
        <Product>
            <LineNumber>10</LineNumber>
            <IsConfig>N</IsConfig>
            <LineITotal>1.00</LineITotal>
        </Product>
        <Product>
            <LineNumber>10-1</LineNumber>
            <IsConfig>N</IsConfig>
            <LineITotal>1.00</LineITotal>
        </Product>
        <Product>
            <LineNumber>10-1-1</LineNumber>
            <IsConfig>N</IsConfig>
            <LineTotal>2.00</LineTotal>
        </Product>
        <Product>
            <LineNumber>10-1-2</LineNumber>
            <IsConfig>N</IsConfig>
            <LineTotal>1.00</LineTotal>
        </Product>
        <Product>
            <LineNumber>10-2</LineNumber>
            <IsConfig>N</IsConfig>
            <LineITotal>4.00</LineITotal>
        </Product>
    </Item>
    <Item>
        <Product>
            <LineNumber>20</LineNumber>
            <IsConfig>N</IsConfig>
            <LineITotal>1.00</LineITotal>
        </Product>
    </Item>
</ItemSection>
<ItemSection>
    <SectionNumber>2</SectionNumber>
    <Item>
        <Product>
            <LineNumber>30</LineNumber>
            <IsConfig>N</IsConfig>
            <LineITotal>1.00</LineITotal>
        </Product>
        <Product>
            <LineNumber>30-1</LineNumber>
            <IsConfig>N</IsConfig>
            <LineITotal>1.00</LineITotal>
        </Product>
        <Product>
            <LineNumber>30-1-1</LineNumber>
            <IsConfig>N</IsConfig>
            <LineTotal>2.00</LineTotal>
        </Product>
        <Product>
            <LineNumber>30-1-2</LineNumber>
            <IsConfig>N</IsConfig>
            <LineTotal>1.00</LineTotal>
        </Product>
        <Product>
            <LineNumber>30-2</LineNumber>
            <IsConfig>N</IsConfig>
            <LineITotal>4.00</LineITotal>
        </Product>
    </Item>
    <Item>
        <Product>
            <LineNumber>40</LineNumber>
            <IsConfig>N</IsConfig>
            <LineITotal>1.00</LineITotal>
        </Product>
    </Item>
</ItemSection>

This is a simple version of the actual XML - the actual one has a billion elements at the same level as Line Number that need to be moved over. I know how to use brute force and copy every field over one by one and can use recursive templates for the line item section but I am hoping to get some pointers here for a more efficient approach. Thanks.

هل كانت مفيدة؟

المحلول

try the following stylesheet:

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

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

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

    <xsl:template match="Product">
        <xsl:copy>
            <xsl:apply-templates select="*[not(self::Config)]"/>
        </xsl:copy>
        <xsl:apply-templates select="Config"/>
    </xsl:template>

    <xsl:template match="Config">
        <xsl:apply-templates/>
    </xsl:template>

</xsl:stylesheet>

the output is as exact as your requirement.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top