-1

XSL is used to de-normalize XML for importing into flat database table.

For every invoice invoiceid column must contain this invoice id.

However for unknown reason

    <xsl:value-of select="../../../../../../Invoice/@invoiceId"/>

returns always first invoice id 1605002 in arvenumber element. So all rows have same id. How to fix ?

XML:

<?xml version="1.0" encoding="windows-1257"?>

<Envelope>
  <Body>
    <BuyInvoicesResponse>
      <E_Invoice>
        <Invoice invoiceId='1605002'>
          <InvoiceItem>
            <InvoiceItemGroup>
              <ItemEntry>
                <SellerProductId>YEYLD</SellerProductId>
                <Description>Üldelekter</Description>
                <EAN>23225325</EAN>
                <ItemDetailInfo>
                  <ItemUnit>m2</ItemUnit>
                  <ItemAmount>1.96</ItemAmount>
                  <ItemPrice>1</ItemPrice>
                </ItemDetailInfo>
                <ItemSum>1.96</ItemSum>
                <VAT>
                  <SumBeforeVAT>1.96</SumBeforeVAT>
                  <VATRate>0.00</VATRate>
                  <VATSum>0.00</VATSum>
                </VAT>
                <ItemTotal>1.96</ItemTotal>
              </ItemEntry>
              <ItemEntry>
                <SellerProductId>YKV</SellerProductId>
                <Description>Vesi ja kanalisatsioon</Description>
                <EAN></EAN>
                <ItemDetailInfo>
                  <ItemUnit>m3</ItemUnit>
                  <ItemAmount>4.10</ItemAmount>
                  <ItemPrice>2.07600</ItemPrice>
                </ItemDetailInfo>
                <ItemSum>8.51</ItemSum>
                <VAT>
                  <SumBeforeVAT>8.51</SumBeforeVAT>
                  <VATRate>0.00</VATRate>
                  <VATSum>0.00</VATSum>
                </VAT>
                <ItemTotal>8.51</ItemTotal>
              </ItemEntry>
              <ItemEntry>
                <SellerProductId>YPRYGI</SellerProductId>
                <Description>Prügivedu</Description>
                <EAN></EAN>
                <ItemDetailInfo>
                  <ItemUnit>m2</ItemUnit>
                  <ItemAmount>1.84</ItemAmount>
                  <ItemPrice>1</ItemPrice>
                </ItemDetailInfo>
                <ItemSum>1.84</ItemSum>
                <VAT>
                  <SumBeforeVAT>1.84</SumBeforeVAT>
                  <VATRate>0.00</VATRate>
                  <VATSum>0.00</VATSum>
                </VAT>
                <ItemTotal>1.84</ItemTotal>
              </ItemEntry>
              <ItemEntry>
                <SellerProductId>YSV</SellerProductId>
                <Description>Vee soojendamine</Description>
                <EAN></EAN>
                <ItemDetailInfo>
                  <ItemUnit>m3</ItemUnit>
                  <ItemAmount>1.50</ItemAmount>
                  <ItemPrice>2.10600</ItemPrice>
                </ItemDetailInfo>
                <ItemSum>3.16</ItemSum>
                <VAT>
                  <SumBeforeVAT>3.16</SumBeforeVAT>
                  <VATRate>0.00</VATRate>
                  <VATSum>0.00</VATSum>
                </VAT>
                <ItemTotal>3.16</ItemTotal>
              </ItemEntry>
            </InvoiceItemGroup>
          </InvoiceItem>
        </Invoice>
        <Invoice invoiceId='1605006'>
          <InvoiceItem>
            <InvoiceItemGroup>
              <ItemEntry>
                <SellerProductId>YEYLD</SellerProductId>
                <Description>Üldelekter</Description>
                <EAN>23225325</EAN>
                <ItemDetailInfo>
                  <ItemUnit>m2</ItemUnit>
                  <ItemAmount>2.50</ItemAmount>
                  <ItemPrice>1</ItemPrice>
                </ItemDetailInfo>
                <ItemSum>2.50</ItemSum>
                <VAT>
                  <SumBeforeVAT>2.50</SumBeforeVAT>
                  <VATRate>0.00</VATRate>
                  <VATSum>0.00</VATSum>
                </VAT>
                <ItemTotal>2.50</ItemTotal>
              </ItemEntry>
            </InvoiceItemGroup>
          </InvoiceItem>
        </Invoice>
      </E_Invoice>

    </BuyInvoicesResponse>
  </Body>
</Envelope>

XSL:

<?xml version="1.0" encoding="ISO-8859-1" standalone="no" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" version="1.0" encoding="UTF-8" standalone="yes"/>
  <xsl:template match="/">
    <xsl:element name="VFPData">
      <xsl:apply-templates/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="/Envelope/Body/BuyInvoicesResponse/E_Invoice/Invoice/InvoiceItem/InvoiceItemGroup/ItemEntry/Accounting/*">
    <xsl:element name="Document-BuyInvoice">
      <xsl:element name="arvenumber">
        <xsl:value-of select="../../../../../../Invoice/@invoiceId"/>
      </xsl:element>
      <xsl:element name="nimetus">
        <xsl:value-of select="../../Description"/>
      </xsl:element>
    </xsl:element>
  </xsl:template>

  <!-- to ommit nodes data -->
  <xsl:template match="text()">
  </xsl:template>

  <!-- to work over every node -->
  <xsl:template match="*">
    <xsl:apply-templates/>
  </xsl:template>

</xsl:stylesheet>

MSXML parser is used for conversion

Andrus
  • 26,339
  • 60
  • 204
  • 378

1 Answers1

1

If you want the InvoiceID on the nearest enclosing Invoice element, try writing ancestor::Invoice[1]/@invoiceId instead of ../../../../../../Invoice/@invoiceId.

The XPath you show climbs laboriously up the XML element tree until it reaches the E_Invoice element (that's the sixfold ..), then descends to the children of that element named Invoice, and their invoiceId attributes. Since there are many Invoice elements which are children of E_Invoice, the value of the XPath expression shown is a set of attribute nodes. Since xsl:value-of only wants one value, it takes the first and throws the rest away.

The key to avoiding this problem is to avoid climbing up past the Invoice element you want, because then you have to climb back down, and how are you going to know which of the many Invoice elements you actually want? The ancestor axis allows you to climb to the Invoice element and no further, thus avoiding any ambiguity about which Invoice element you want: you want the one which is the ancestor of the current node.

C. M. Sperberg-McQueen
  • 24,596
  • 5
  • 38
  • 65