juls_pro_37: XSLT 1.0 Sum

Hi,

bitte um Hilfe.

Ich versuche das Feld Item.SalesPrice anhand einer Abfrage neu zu berechnen.

Error-Meldung: Error in expression format-number(sum(//Item[concat(FixedPriceGroupID, '|', SalesOriginId = 'PES_CNT') = current()/concat(FixedPriceGroupID, '|', SalesOriginId = 'PES_CNT')]/SalesPrice), '#0.00'): Unexpected token [<function>] in path expression -> Saxon 6.5.5

-> 2 Schwierigkeiten:

  • Mit meinem Code wird ein weiteres Feld Item.SalesPrice erstellt und nicht das vorhandene neu berechnet.
  • Dieser Code scheint nur via 2.0 zu funktionieren - arbeite aber mit der Version 1.0

Beispiel XML:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<SALESINVOICE>
  <Interchange>
    <Recipient>test</Recipient>
    <Sender>test1</Sender>   
  </Interchange>
  <HeaderInformation>
    <OrigInvoiceNumber>1</OrigInvoiceNumber>
    <InvoiceType>INVOIC</InvoiceType>
    <InvoiceDate>2022-10-20</InvoiceDate>
    <InvoiceNumber>test</InvoiceNumber>
  </HeaderInformation>
  <LineInformation>
    <Item>
      <LineNum>1</LineNum>
      <GTIN>12324324324324</GTIN>
      <SupplierArticleNumber>P0000000</SupplierArticleNumber>
      <FixedPrice>381.3500</FixedPrice>
      <SalesPrice>3.63</SalesPrice>
      <SalesOriginId>PES_CNT</SalesOriginId>
      <FixedPriceGroupID>1</FixedPriceGroupID>
      <FixedPriceGroupDescription>test1</FixedPriceGroupDescription>
      <LineText>
        <Qualifier>INV</Qualifier>
        <Text>Text5</Text>
      </LineText>
	        <LineText>
        <Qualifier>INV</Qualifier>
        <Text>Text55</Text>
      </LineText>
	        <LineText>
        <Qualifier>INV</Qualifier>
        <Text>Text5</Text>
      </LineText>
	        <LineText>
        <Qualifier>INV</Qualifier>
        <Text>Text55</Text>
      </LineText>
    </Item>
    <Item>
      <LineNum>2</LineNum>
      <GTIN>56546546546546546546</GTIN>      
      <SupplierArticleNumber>P0000000</SupplierArticleNumber>
      <TotalQuantity>100.00</TotalQuantity>
      <SalesPrice>0.19</SalesPrice>
      <SalesOriginId>PES_CNT</SalesOriginId>
      <FixedPriceGroupID>1</FixedPriceGroupID>
      <FixedPriceGroupDescription>test2</FixedPriceGroupDescription>
    </Item>
    <Item>
      <LineNum>3</LineNum>
      <GTIN>657777657657567</GTIN>      
      <SupplierArticleNumber>P0000000</SupplierArticleNumber>
      <TotalQuantity>100.00</TotalQuantity>
      <SalesPrice>0.08</SalesPrice>
      <SalesOriginId>PES_CNT</SalesOriginId>
      <FixedPriceGroupID>2</FixedPriceGroupID>
      <FixedPriceGroupDescription>test3</FixedPriceGroupDescription>
      <LineText>
        <Qualifier>INV</Qualifier>
        <Text>Text3</Text>
      </LineText>
	        <LineText>
        <Qualifier>INV</Qualifier>
        <Text>Text33</Text>
      </LineText>
	        <LineText>
        <Qualifier>INV</Qualifier>
        <Text>Text3</Text>
      </LineText>
	        <LineText>
        <Qualifier>INV</Qualifier>
        <Text>Text33</Text>
      </LineText>
    </Item>
    <Item>
      <LineNum>4</LineNum>
      <GTIN>22222222222</GTIN>      
      <SupplierArticleNumber>P0000000</SupplierArticleNumber>
      <TotalQuantity>100.00</TotalQuantity>
      <SalesPrice>0.51</SalesPrice>
      <SalesOriginId>PES_CNT</SalesOriginId>
      <FixedPriceGroupID>2</FixedPriceGroupID>
      <FixedPriceGroupDescription>test4</FixedPriceGroupDescription>
    </Item>
  </LineInformation>
</SALESINVOICE>

XSLT:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    
    <xsl:output method="xml" indent="yes" encoding="UTF-8"/>
    
    <xsl:strip-space elements="*" />    
    
    <xsl:key name="SalesPriceCalculated" match="Item" use="concat(FixedPriceGroupID, '|', SalesOriginId = 'PES_CNT')"/>
    
    <!-- Identity-Template für die nicht explizit benannten Elemente -->
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="Item">
        <Item>
            <xsl:for-each select="current()[generate-id() = generate-id(key('SalesPriceCalculated', concat(FixedPriceGroupID, '|', SalesOriginId = 'PES_CNT')))]">
                
                <SalesPrice>
                    <xsl:value-of select="format-number(sum(//Item[concat(FixedPriceGroupID, '|', SalesOriginId = 'PES_CNT') = current()/concat(FixedPriceGroupID, '|', SalesOriginId = 'PES_CNT')]/SalesPrice), '#0.00')"/>
                </SalesPrice>
                
            </xsl:for-each>
            <xsl:apply-templates select="@* | node()"/>
        </Item>   
    </xsl:template>
    
    <!-- delete empty nodes -->
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>  
    
    <xsl:template match="*[not(@*|*|comment()|processing-instruction()) and normalize-space()='']"/>
    
</xsl:stylesheet>

Danke & LG Julian

  1. Hi,

    -> 2 Schwierigkeiten:

    • Mit meinem Code wird ein weiteres Feld Item.SalesPrice erstellt und nicht das vorhandene neu berechnet.

    Du sagst ja auch nach der Schleife für das Neuerstellen des SalesPrice-Elements, daß für alle vorhandenen Sub-Elemente ein apply-templates gemacht werden soll.

    Und da kein spezielleres Template vorhanden ist, wird das Template mit dem copy auch auf SalesPrice angewandt.

    Also muß entweder ein Template für SalesPrice vorhanden sein, daß nix macht, oder eben SalesPrice ausgeklammert werden bei dem apply-template …

    • Dieser Code scheint nur via 2.0 zu funktionieren - arbeite aber mit der Version 1.0

    dann finde heraus, welches der vewendeten Features in 1.0 nicht verfügbar ist, und versuche, das zu ersetzen.

    Oder rüste auf 2.0 auf …

    (Mann, bin ich froh, daß ich nix mehr mit XSLT machen muß …)

    cu,
    Andreas a/k/a MudGuard

    1. klingt einfacher als es ist :( ich komm nicht mehr weiter.

      trotz stundenlanger suche und versuche...

    2. denke die Lösung ist doch etwas näher als gedacht:

          <xsl:template match="SalesPrice">
              <xsl:copy>
                  <xsl:value-of select="sum(key('SalesPriceCalculated', concat(../FixedPriceGroupID, '|', ../SalesOriginId = 'PES_CNT'))/SalesPrice)"/>
              </xsl:copy>
          </xsl:template>
      
    3. Hallo Andreas,

      Oder rüste auf 2.0 auf …

      (Mann, bin ich froh, daß ich nix mehr mit XSLT machen muß …)

      Ich bin froh, dass sich XSLT und XPath in Richtung 4.0 weiterentwickeln (wobei die 2.0-Specs auch schon 15 Jahre existieren). 😉

      Grüße,
      Thomas

      1. Hi,

        (Mann, bin ich froh, daß ich nix mehr mit XSLT machen muß …) Ich bin froh, dass sich XSLT und XPath in Richtung 4.0 weiterentwickeln (wobei die 2.0-Specs auch schon 15 Jahre existieren). 😉

        wir hatten früher einen Prozeß, bei dem aus dem Datenbank-Kram zuerst ein riesiges XML gemacht wurde, das dann per XSLT 1 zu einem Text umgeformt wurde. Mit verschiedenen XSLT-Templates für verschiedene Zwecke.

        Das war immer ein nerviges Gehampel. Und hat Zeit gekostet. Alleine das XML zu erstellen mehrere Sekunden …

        Irgendwann haben wir das dann umgestellt auf Velocity-Templates, da war der Prozeß dann in weniger als einer Zehntel-Sekunde fertig.

        Und der Code war dann so einfach, daß kleine Änderungen auch von Nicht-Informatikern gemacht werden konnten.

        cu,
        Andreas a/k/a MudGuard

        1. Hallo Andreas,

          Und der Code war dann so einfach, daß kleine Änderungen auch von Nicht-Informatikern gemacht werden konnten.

          XSLT (und auch XML allgemein) ist ja gerade eine Technologie mit der sich die Informatikzunft wenig bis gar nicht identifiziert. Das macht dann eher die Technische Kommunikation. Von daher auch meine Befassung damit.

          Grüße,
          Thomas

      2. Hi,

        Ich bin froh, dass sich XSLT und XPath in Richtung 4.0 weiterentwickeln (wobei die 2.0-Specs auch schon 15 Jahre existieren). 😉

        Hab das eben mal überflogen - da hat sich ja einiges getan seit 1.0 (das ich damals verwenden mußte)

        Aber ich bin trotzdem froh, nicht mehr mit xslt arbeiten zu müssen.

        cu,
        Andreas a/k/a MudGuard