1

I have requirement as below to implement transformation using only XSL1.0,

  1. First condition is Group line items based on parentLineNumber.
  2. Then the second condition is to ignore the invoice line when ParentLinenumber and LineNumber is same when only if group has more than one invoice line item.

Sample Input:

<InvoiceNotification>
    <Invoice>
        <InvoiceLineItem>
            <LineSection>
                <parentLineNumber>000010</parentLineNumber>
            </LineSection>
            <LineNumber>000010</LineNumber>
            <proprietaryInformation>
                <FreeFormText>PK06</FreeFormText>
            </proprietaryInformation>
        </InvoiceLineItem>
        <InvoiceLineItem>
            <LineSection>
                <parentLineNumber>000010</parentLineNumber>
            </LineSection>
            <LineNumber>000011</LineNumber>
            <proprietaryInformation>
                <FreeFormText>PK07</FreeFormText>
            </proprietaryInformation>
        </InvoiceLineItem>
        <InvoiceLineItem>
            <LineSection>
                <parentLineNumber>000010</parentLineNumber>
            </LineSection>
            <LineNumber>000012</LineNumber>
            <proprietaryInformation>
                <FreeFormText>PK08</FreeFormText>
            </proprietaryInformation>
        </InvoiceLineItem>
        <InvoiceLineItem>
            <LineSection>
                <parentLineNumber>000020</parentLineNumber>
            </LineSection>
            <LineNumber>000020</LineNumber>
            <proprietaryInformation>
                <FreeFormText>GK01</FreeFormText>
            </proprietaryInformation>
        </InvoiceLineItem>
    </Invoice>
</InvoiceNotification>

I have developed below XSLT which is partially working.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>
    <xsl:key name="Invoices" match="InvoiceLineItem" use="LineSection/parentLineNumber"/>
    <xsl:template match="InvoiceNotification">
        <Invoices>
            <xsl:for-each select="Invoice/InvoiceLineItem [ count ( key('Invoices',LineSection/parentLineNumber)[1] | . ) = 1 ]">
                <Batchorder>
                    <xsl:for-each select="key('Invoices',LineNumber)">
                        <Items>
                            <LineItem>
                                <xsl:value-of select="proprietaryInformation"/>
                            </LineItem>
                        </Items>
                    </xsl:for-each>
                </Batchorder>
            </xsl:for-each>
        </Invoices>
    </xsl:template>
</xsl:stylesheet>

Resulted output:

<?xml version="1.0" encoding="UTF-8"?>
<Invoices>
    <Batchorder>
        <Items>
            <proprietaryInformation>PK06</proprietaryInformation>
        </Items>
        <Items>
            <proprietaryInformation>PK07</proprietaryInformation>
        </Items>
        <Items>
            <proprietaryInformation>PK08</proprietaryInformation>
        </Items>
    </Batchorder>
    <Batchorder>
        <Items>
            <proprietaryInformation>GK01</proprietaryInformation>
        </Items>
    </Batchorder>
</Invoices>

But I am expecting below output,

<?xml version="1.0" encoding="UTF-8"?>
<Invoices>
    <Batchorder>
        <Items>
            <proprietaryInformation>PK07</proprietaryInformation>
        </Items>
        <Items>
            <proprietaryInformation>PK08</proprietaryInformation>
        </Items>
    </Batchorder>
    <Batchorder>
        <Items>
            <proprietaryInformation>GK01</proprietaryInformation>
        </Items>
    </Batchorder>
</Invoices>
Daniel Haley
  • 51,389
  • 6
  • 69
  • 95

2 Answers2

1

You can use a predicate on the for-each I think:

<xsl:for-each select="key('Invoices',LineNumber)[LineNumber != LineSection/parentLineNumber or count(key('Invoices', LineNumber)) = 1]">
Martin Honnen
  • 160,499
  • 6
  • 90
  • 110
  • I don't think this can work without applying a similar predicate to the key. But I did not fully understand OP's requirement, so I could be wrong. – michael.hor257k Aug 05 '20 at 04:19
1

Almost the same solution as the one proposed by Martin Honnen, but probably a little bit more efficient:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
    <xsl:key name="Invoices" match="InvoiceLineItem" use="LineSection/parentLineNumber"/>
    <xsl:template match="InvoiceNotification">
        <Invoices>
            <xsl:for-each select=
            "Invoice/InvoiceLineItem
            [count ( key('Invoices',LineSection/parentLineNumber)[1] | . ) = 1]">
                <Batchorder>
                    <xsl:for-each select="key('Invoices',LineNumber)
                    [not(LineNumber = LineSection/parentLineNumber)
                    or not(key('Invoices',LineNumber)[2])]">
                        <Items>
                            <LineItem>
                                <xsl:value-of select="proprietaryInformation"/>
                            </LineItem>
                        </Items>
                    </xsl:for-each>
                </Batchorder>
            </xsl:for-each>
        </Invoices>
    </xsl:template>
</xsl:stylesheet>

When this transformation is applied on the provided source XML document:

<InvoiceNotification>
    <Invoice>
        <InvoiceLineItem>
            <LineSection>
                <parentLineNumber>000010</parentLineNumber>
            </LineSection>
            <LineNumber>000010</LineNumber>
            <proprietaryInformation>
                <FreeFormText>PK06</FreeFormText>
            </proprietaryInformation>
        </InvoiceLineItem>
        <InvoiceLineItem>
            <LineSection>
                <parentLineNumber>000010</parentLineNumber>
            </LineSection>
            <LineNumber>000011</LineNumber>
            <proprietaryInformation>
                <FreeFormText>PK07</FreeFormText>
            </proprietaryInformation>
        </InvoiceLineItem>
        <InvoiceLineItem>
            <LineSection>
                <parentLineNumber>000010</parentLineNumber>
            </LineSection>
            <LineNumber>000012</LineNumber>
            <proprietaryInformation>
                <FreeFormText>PK08</FreeFormText>
            </proprietaryInformation>
        </InvoiceLineItem>
        <InvoiceLineItem>
            <LineSection>
                <parentLineNumber>000020</parentLineNumber>
            </LineSection>
            <LineNumber>000020</LineNumber>
            <proprietaryInformation>
                <FreeFormText>GK01</FreeFormText>
            </proprietaryInformation>
        </InvoiceLineItem>
    </Invoice>
</InvoiceNotification>

the wanted, correct result is produced:

<Invoices>
   <Batchorder>
      <Items>
         <LineItem>
                PK07
            </LineItem>
      </Items>
      <Items>
         <LineItem>
                PK08
            </LineItem>
      </Items>
   </Batchorder>
   <Batchorder>
      <Items>
         <LineItem>
                GK01
            </LineItem>
      </Items>
   </Batchorder>
</Invoices>
Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431