0

I have a need to split an XML file based on a tag inside. Here is the input file will look like. The spli should happen based on Order tag

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<Root>
    <MultiApi>
        <API>
            <Input>
                <Order test="0001" >
                    <OrderLines>
                        <OrderLine test1="123" />
                    </OrderLines>
                </Order>
                <Order test="0002" >
                    <OrderLines>
                        <OrderLine test1="456" />
                    </OrderLines>
                </Order>
                <Order test="0003" >
                    <OrderLines>
                        <OrderLine test1="789" />
                    </OrderLines>
                </Order>
            </Input>
        </API>
    </MultiApi>
    <MultiApi>
        <EOF abc="test" MaxMsgPerFile="1" >
        </EOF>
    </MultiApi>
    </Root>

The output should look like:

<Root>
<MultiApi>
    <API>
        <Input>
            <Order test="0001" >
                <OrderLines>
                    <OrderLine test1="123" />
                </OrderLines>
            </Order>
        </Input>
    </API>
</MultiApi>
<MultiApi>
    <API>
        <Input>
            <Order test="0002" >
                <OrderLines>
                    <OrderLine test1="456" />
                </OrderLines>
            </Order>
        </Input>
    </API>
</MultiApi>
<MultiApi>
    <API>
        <Input>
            <Order test="0003" >
                <OrderLines>
                    <OrderLine test1="789" />
                </OrderLines>
            </Order>
        </Input>
    </API>
</MultiApi>
</Root>

I have tried the below XSL - but was returning null. Any help would be great:

<?xml version="1.0" encoding="UTF-8"?>
<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:variable name="tag">
      <xsl:value-of select="/*/*/EOF/@MaxMsgPerFile"/>
   </xsl:variable>

<xsl:template match="/Root">
    <xsl:copy>


        <xsl:for-each select="MultiApi[not (EOF)]/API/Input/Order[position() mod $tag = 1]">
            <MultiApi>
                <xsl:copy-of select="| . | following-sibling::Order[position() &lt; $tag]"/>

            </MultiApi>
        </xsl:for-each>
    </xsl:copy>
</xsl:template> 

</xsl:stylesheet>

I may not be doing a good job with "following-sibling". Please review and help!

2
  • XSLT 1.0 cannot produce multiple files as a result of a single transformation (unless your processor happens to support the EXLT exsl:document extension element). Commented May 9, 2019 at 17:02
  • I get your point and I just adjusted the question. Thanks @michael.hor257k Commented May 9, 2019 at 17:34

1 Answer 1

2

Only requiring one output file, you can easily achieve this with the following stylesheet. The [not(EOF)] predicate on the MultiApi element is not necessary, because the other element does not contain this structure.

<?xml version="1.0" encoding="UTF-8"?>
<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:variable name="tag">
        <xsl:value-of select="/*/*/EOF/@MaxMsgPerFile"/>
    </xsl:variable>

    <xsl:template match="/Root">
        <xsl:copy>
            <xsl:for-each select="MultiApi/API/Input/Order">
                <MultiApi>
                    <API>
                        <Input>
                            <xsl:copy-of select="."/>
                        </Input>
                    </API>
                </MultiApi>
            </xsl:for-each>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

Its output is:

<?xml version="1.0" encoding="UTF-8"?>
<Root>
    <MultiApi>
        <API>
            <Input>
                <Order test="0001">
                    <OrderLines>
                        <OrderLine test1="123"/>
                    </OrderLines>
                </Order>
            </Input>
        </API>
    </MultiApi>
    <MultiApi>
        <API>
            <Input>
                <Order test="0002">
                    <OrderLines>
                        <OrderLine test1="456"/>
                    </OrderLines>
                </Order>
            </Input>
        </API>
    </MultiApi>
    <MultiApi>
        <API>
            <Input>
                <Order test="0003">
                    <OrderLines>
                        <OrderLine test1="789"/>
                    </OrderLines>
                </Order>
            </Input>
        </API>
    </MultiApi>
</Root>
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks much. I think I over-complicated this. :) Thank you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.