Home > Net >  Lookup XML using XSLT
Lookup XML using XSLT

Time:12-13

I got stuck with my code using a lookup XML with an XSLT

my XML is like this:

<?xml version="1.0"?>
<Invoices>
   <invoice>
      <customer>
         <name>Juan tamban</name>
      </customer>
      <details>
         <VAT>0001</VAT>
         <items>
            <item code="I01" name="Item1" />
            <item code="I02" name="Item2" />
         </items>
      </details>
   </invoice>
   <invoice>
      <customer>
         <name>Johny Cash</name>
      </customer>
      <details>
         <VAT>0002</VAT>
         <items>
            <item code="I03" name="Item3" />
            <item code="I04" name="Item4" />
         </items>
      </details>
   </invoice>
</Invoices>

And my current XSLT looks like this:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
   <xsl:output method="xml" indent="yes"/>

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

   <xsl:variable name="lookupdoc" select="document('Lookup.xml')/VATS/VAT"/>

   <xsl:key name="VAT-by-id" match="VAT" use="@id"/>

   <xsl:template name="getCode">
      <xsl:param name="VATNumber" />
      <xsl:variable name="VATId" select="$VATNumber/."/>
      <xsl:for-each select="$lookupdoc">
         <xsl:value-of select="key('VAT-by-id', $VATId/VAT)/code"/>
      </xsl:for-each>
   </xsl:template>

   <xsl:template match="items/item">
      <Item>
         <ItemCOde>
            <xsl:value-of select="@code"/>
         </ItemCOde>
         <ItemName>
            <xsl:value-of select="@name"/>
         </ItemName>
      </Item>
   </xsl:template>

   <xsl:template match="invoice">
      <xsl:variable name="VAT">
         <xsl:call-template name="getCode">
            <xsl:with-param name="VATNumber" select="details/VAT" />
         </xsl:call-template>
      </xsl:variable>

      <InvoiceDetails>
         <CustomerName>
            <xsl:value-of select="customer/name"/>
         </CustomerName>
         <VATCode>
            <xsl:value-of select="$VAT" />
         </VATCode>
         <xsl:apply-templates select="details/items/item" />
      </InvoiceDetails>
   </xsl:template>

   <xsl:template match="Invoices">
      <Invoices>
         <xsl:apply-templates select ="invoice"/>
      </Invoices>
   </xsl:template>
</xsl:stylesheet>

And my lookup XML is this:

<?xml version="1.0" encoding="utf-8"?>
<VATS>
   <VAT id="0001" code="0001-000101/08-12-2021"/>
   <VAT id="0002" code="0002-000102/09-12-2021"/>
   <VAT id="0003" code="0003-000103/10-12-2021"/>
   <VAT id="0004" code="0004-000104/11-12-2021"/>
</VATS>

My result is like this, and as you can see the VATCode tag is not filled in:

<?xml version="1.0" encoding="utf-8"?>
<Invoices>
  <InvoiceDetails>
    <CustomerName>Juan tamban</CustomerName>
    <VATCode></VATCode>
    <Item>
      <ItemCOde>I01</ItemCOde>
      <ItemName>Item1</ItemName>
    </Item>
    <Item>
      <ItemCOde>I02</ItemCOde>
      <ItemName>Item2</ItemName>
    </Item>
  </InvoiceDetails>
  <InvoiceDetails>
    <CustomerName>Johny Cash</CustomerName>
    <VATCode></VATCode>
    <Item>
      <ItemCOde>I03</ItemCOde>
      <ItemName>Item3</ItemName>
    </Item>
    <Item>
      <ItemCOde>I04</ItemCOde>
      <ItemName>Item4</ItemName>
    </Item>
  </InvoiceDetails>
</Invoices>

Anyone can let me know what is missing or what is wrong with this code?

Thanks for the help.

CodePudding user response:

Your code will work if you change this:

<xsl:variable name="lookupdoc" select="document('Lookup.xml')/VATS/VAT"/>

to:

<xsl:variable name="lookupdoc" select="document('Lookup.xml')"/>

and this:

   <xsl:template name="getCode">
      <xsl:param name="VATNumber" />
      <xsl:variable name="VATId" select="$VATNumber/."/>
      <xsl:for-each select="$lookupdoc">
         <xsl:value-of select="key('VAT-by-id', $VATId/VAT)/code"/>
      </xsl:for-each>
   </xsl:template>

to:

   <xsl:template name="getCode">
      <xsl:param name="VATNumber" />
      <xsl:for-each select="$lookupdoc">
         <xsl:value-of select="key('VAT-by-id', $VATNumber)/@code"/>
      </xsl:for-each>
   </xsl:template>

Of course, you could shorten the whole thing to:

<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:param name="lookupdoc" select="document('Lookup.xml')"/>

<xsl:key name="VAT-by-id" match="VAT" use="@id"/>

<xsl:template match="/Invoices">
    <Invoices>
        <xsl:apply-templates select="invoice"/>
    </Invoices>
</xsl:template>

<xsl:template match="invoice">
    <InvoiceDetails>
        <CustomerName>
            <xsl:value-of select="customer/name"/>
        </CustomerName>
         <VATCode>
            <xsl:variable name="VATNumber" select="details/VAT" />
            <xsl:for-each select="$lookupdoc">
                <xsl:value-of select="key('VAT-by-id', $VATNumber)/@code"/>
            </xsl:for-each>
         </VATCode>
        <xsl:apply-templates select="details/items/item" />
    </InvoiceDetails>
</xsl:template>

<xsl:template match="items/item">
    <Item>
        <ItemCOde>
            <xsl:value-of select="@code"/>
         </ItemCOde>
        <ItemName>
            <xsl:value-of select="@name"/>
         </ItemName>
    </Item>
</xsl:template>

</xsl:stylesheet>

P.S. I believe your decision to use a key is the correct one.

CodePudding user response:

I think you have shot yourself into the foot trying to use the key, you just want

   <xsl:template name="getCode">
      <xsl:param name="VATNumber" />
      <xsl:for-each select="$lookupdoc">
         <xsl:value-of select="key('VAT-by-id', $VATNumber)/@code"/>
      </xsl:for-each>
   </xsl:template>

I would also change <xsl:variable name="lookupdoc" select="document('Lookup.xml')/VATS/VAT"/> to <xsl:variable name="lookupdoc" select="document('Lookup.xml')"/>, as you just want and need the document node for the context switch when using the key so there is no advantage in selecting downwards.

  • Related