Les
Les

Reputation: 29

Transform an XML by grouping the fields

My knowledge to XSLT is limited but always eager to learn. I am currently working on a template that requires to transform the XML input. I've been trying to group the InvoiceNum fields and not getting anywhere. I am getting an error: Envision.Utilities.XsltEngine-Object reference not set to an instance of an object.

Here's the input XML for reference:

<?xml version='1.0' ?>
  <Request>
  <Information>
    <ImageID>987456321</ImageID>
    <Contract>123456789</Contract>
    <Lastname>MICKEYMOUSE</Lastname>
  </Information>
<Document>
    <InvoiceNum>123456823</InvoiceNum>
    <Reference>AD20985224</Reference>
    <InvoiceNum>100000123</InvoiceNum>
    <Reference>AS20101387</Reference>
    <InvoiceNum>858511825</InvoiceNum>
    <Reference>GF96844</Reference>
    <InvoiceNum>885154145</InvoiceNum>
    <Reference>FGFD2018</Reference>
    <InvoiceNum>25241111</InvoiceNum>
    <Reference>SD88888</Reference>
    <InvoiceNum>8571414</InvoiceNum>
    <Reference>DF864841254</Reference>
    </Document>
 </Request>

Here's my XSLT format for reference: What am I missing? Is there better way to format the XSLT template I have currently below? Any help is greatly appreciated.

<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:strip-space elements="*"/>
<xsl:param name="cols" select="3" />

<xsl:template match="Request">
 <table border="1">
 <xsl:apply-templates select="InvoiceNum[position() mod $cols = 1]"/>
 </table>
 </xsl:template>

<xsl:template match="Document">
<xsl:variable name="group" select=". | following-sibling::InvoiceNum
[position() &lt; $cols]" />
<xsl:for-each select="*">
<xsl:variable name="i" select="position()" />
<Invoice>
<InvoiceNumber>
<xsl:value-of select="InvoiceNum()"/>
</InvoiceNumber>
 <xsl:for-each select="$group">
 <xsl:value-of select="*[$i]"/>
 </xsl:for-each>
 </Invoice>
 </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

Here's the XML output I'd like to have:

<InvCase>
  <Invoices>
    <InvoicemNumber>InvoiceNum1</InvoicemNumber>
    <InvoicemNumber>InvoiceNum2</InvoicemNumber>
    <InvoicemNumber>InvoiceNum3</InvoicemNumber>
 </Invoices>
</InvCase>

Upvotes: 0

Views: 38

Answers (1)

Tim C
Tim C

Reputation: 70598

It looks like you are trying to group in the InvoiceNum into groups of 3. The first issue you have is that in your template matching Request you do this...

<xsl:apply-templates select="InvoiceNum[position() mod $cols = 1]"/>

But InvoiceNum is not a child of Request, and so that selects nothing. You probably need to do this...

Additionally, you have a template matching Document, but this probably needs to match InvoiceNum (Doing following-sibling::InvoiceNum would not return anything if you were matching Document as the InvoiceNum elements are children of Document not following siblings).

Try this XSLT

<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:strip-space elements="*"/>
<xsl:param name="cols" select="3" />

<xsl:template match="Request">
 <InvCases>
   <xsl:apply-templates select="Document/InvoiceNum[position() mod $cols = 1]"/>
 </InvCases>
</xsl:template>

<xsl:template match="InvoiceNum">
  <xsl:variable name="group" select=". | following-sibling::InvoiceNum[position() &lt; $cols]" />
  <Invoice>
   <xsl:for-each select="$group">
    <InvoiceNumber>
      <xsl:value-of select="."/>
    </InvoiceNumber>
   </xsl:for-each>
  </Invoice>
 </xsl:template>
</xsl:stylesheet>

Upvotes: 1

Related Questions