juls_pro_37: XSLT-SUM

Hi,

benötige bitte wieder eure Hilfe.

Wie kann ich den Wert unter "ItemDeliveryInformation.DeliveredQuantity" summieren, wenn die LineNumDeliveryNote, PackingSlipId und DeliveryDate ident sind? Weiters sollen anschließend die Nodes, welche für die Berechnung verwendet wurden entfernt werden:

aktuell:

<?xml version="1.0" encoding="utf-8"?>
<SALESINVOICE>
  <Interchange>
    <Recipient>1234</Recipient>
  </Interchange>
  <HeaderInformation>
    <OrigInvoiceNumber>1</OrigInvoiceNumber>
  </HeaderInformation>
  <LineInformation>
    <Item>
      <LineNum>1</LineNum>
      <ItemDeliveryInformation>
        <LineNumDeliveryNote>1</LineNumDeliveryNote>
        <PackingSlipId>PAC0029040</PackingSlipId>
        <DeliveryDate>2021-01-08</DeliveryDate>
        <DeliveredQuantity>4.00</DeliveredQuantity>
      </ItemDeliveryInformation>
      <ItemDeliveryInformation>
        <LineNumDeliveryNote>1</LineNumDeliveryNote>
        <PackingSlipId>PAC0029040</PackingSlipId>
        <DeliveryDate>2021-01-08</DeliveryDate>
        <DeliveredQuantity>2.00</DeliveredQuantity>
      </ItemDeliveryInformation>
      <ItemDeliveryInformation>
        <LineNumDeliveryNote>1</LineNumDeliveryNote>
        <PackingSlipId>PAC0029040</PackingSlipId>
        <DeliveryDate>2021-01-08</DeliveryDate>
        <DeliveredQuantity>4.00</DeliveredQuantity>
      </ItemDeliveryInformation>
      <ItemDeliveryInformation>
        <LineNumDeliveryNote>1</LineNumDeliveryNote>
        <PackingSlipId>PAC0029040</PackingSlipId>
        <DeliveryDate>2021-01-08</DeliveryDate>
        <DeliveredQuantity>4.00</DeliveredQuantity>
      </ItemDeliveryInformation>
            <ItemDeliveryInformation>
        <LineNumDeliveryNote>1</LineNumDeliveryNote>
        <PackingSlipId>PAC0029041</PackingSlipId>
        <DeliveryDate>2021-01-08</DeliveryDate>
        <DeliveredQuantity>4.00</DeliveredQuantity>
      </ItemDeliveryInformation>
    </Item>
  </LineInformation>
</SALESINVOICE>

Korrekt:

<?xml version="1.0" encoding="utf-8"?>
<SALESINVOICE>
  <Interchange>
    <Recipient>1234</Recipient>
  </Interchange>
  <HeaderInformation>
    <OrigInvoiceNumber>1</OrigInvoiceNumber>
  </HeaderInformation>
  <LineInformation>
    <Item>
      <LineNum>1</LineNum>
      <ItemDeliveryInformation>
        <LineNumDeliveryNote>1</LineNumDeliveryNote>
        <PackingSlipId>PAC0029040</PackingSlipId>
        <DeliveryDate>2021-01-08</DeliveryDate>
        <DeliveredQuantity>14.00</DeliveredQuantity>
      </ItemDeliveryInformation>
    <ItemDeliveryInformation>
        <LineNumDeliveryNote>1</LineNumDeliveryNote>
        <PackingSlipId>PAC0029041</PackingSlipId>
        <DeliveryDate>2021-01-08</DeliveryDate>
        <DeliveredQuantity>4.00</DeliveredQuantity>
      </ItemDeliveryInformation>
    </Item>
  </LineInformation>
</SALESINVOICE>

Danke & LG Julian

  1. Hallo Julian,

    Wie kann ich den Wert unter "ItemDeliveryInformation.DeliveredQuantity" summieren, …

    XPath hat dafür die passende Funktion.

    … wenn die LineNumDeliveryNote, PackingSlipId und DeliveryDate ident sind?

    Wenn klingt nach einer Bedingung.

    Soweit kann ich hier schon einmal helfen, ich bin nicht mehr so drin in XSLT. Was ich dir aber noch mitgeben kann: Du kannst XML-Quelltext im Forum auch in schön auszeichnen:

    <?xml version="1.0" encoding="utf-8"?>
    <SALESINVOICE>
      <Interchange>
        <Recipient>1234</Recipient>
      </Interchange>
      <HeaderInformation>
        <OrigInvoiceNumber>1</OrigInvoiceNumber>
      </HeaderInformation>
      <LineInformation>
        <Item>
          <LineNum>1</LineNum>
          <ItemDeliveryInformation>
            <LineNumDeliveryNote>1</LineNumDeliveryNote>
            <PackingSlipId>PAC0029040</PackingSlipId>
            <DeliveryDate>2021-01-08</DeliveryDate>
            <DeliveredQuantity>14.00</DeliveredQuantity>
          </ItemDeliveryInformation>
        <ItemDeliveryInformation>
            <LineNumDeliveryNote>1</LineNumDeliveryNote>
            <PackingSlipId>PAC0029041</PackingSlipId>
            <DeliveryDate>2021-01-08</DeliveryDate>
            <DeliveredQuantity>4.00</DeliveredQuantity>
          </ItemDeliveryInformation>
        </Item>
      </LineInformation>
    </SALESINVOICE>
    

    Viele Grüße
    Robert

    1. Hallo Robert,

      Wenn klingt nach einer Bedingung.

      Wenn x/y/z gleich, dann summiere - das klingt nach Gruppieren.

      Und das bedeutet: Geht es um XSLT 1 oder 2? In XSLT1 bricht man sich für diese Aufgabe die Finger (bzw. man braucht das Muenchian Grouping), und in XSLT 2 verwendet man for-each-group.

      Äh - das hat mir Tante Google verraten, ich habe doch keine Ahnung von XSLT... Thooooomas, der XSLT Papst wird gebraucht 😉

      Rolf

      --
      sumpsi - posui - obstruxi
      1. Hi Rolf,

        es geht um XSLT 1 LEIDER...

        Jap, das stimmt - ohne Thomas geht da gar nix. :)

  2. Hallo Julian,

    Wie kann ich den Wert unter "ItemDeliveryInformation.DeliveredQuantity" summieren, wenn die LineNumDeliveryNote, PackingSlipId und DeliveryDate ident sind? Weiters sollen anschließend die Nodes, welche für die Berechnung verwendet wurden entfernt werden:

    Wie bereits gesagt, wird hier Gruppierung benötigt. Die Spezifik der drei identischen Kriterien bekommt man durch Zusammenführung der jeweiligen Inhalte mittels concat() in den Griff. Der Schlüssel (hier group) ist also ein zusammengefasster String, auf den sich wiederum Bezug nehmen lässt.

    Probiere es so:

    <?xml version="1.0" encoding="UTF-8"?>
    <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:key name="group" match="ItemDeliveryInformation" use="concat(LineNumDeliveryNote, PackingSlipId, DeliveryDate)"/>
    
      <xsl:template match="@* | node()">
        <xsl:copy>
          <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
      </xsl:template>
    
      <xsl:template match="ItemDeliveryInformation">
        <xsl:for-each select=".[generate-id() = generate-id(key('group', concat(LineNumDeliveryNote, PackingSlipId, DeliveryDate))[1])]">
          <ItemDeliveryInformation>
            <xsl:copy-of select="LineNumDeliveryNote"/>
            <xsl:copy-of select="PackingSlipId"/>
            <xsl:copy-of select="DeliveryDate"/>
            <DeliveredQuantity>
              <xsl:value-of select="format-number(sum(key('group', concat(LineNumDeliveryNote, PackingSlipId, DeliveryDate))/DeliveredQuantity), '#.00')"/>
            </DeliveredQuantity>
          </ItemDeliveryInformation>
        </xsl:for-each>
      </xsl:template>
    
    </xsl:stylesheet>
    

    Grüße,
    Thomas

    1. Hi Thomas, thx schon mal.

      bekomm folg. Fehler:

      Error in expression .[generate-id() = generate-id(key('group', concat(LineNumDeliveryNote, PackingSlipId, DeliveryDate))[1])]: Unexpected token [ beyond end of expression

      LG Julian

      1. Hallo Julian,

        bekomm folg. Fehler:

        Error in expression .[generate-id() = generate-id(key('group', concat(LineNumDeliveryNote, PackingSlipId, DeliveryDate))[1])]: Unexpected token [ beyond end of expression

        Habe den 1.0-Code mit Saxon-HE ausgeführt und der denkt grundsätzlich auch nach höheren Versionsregeln.

        Problem liegt offenbar am Punkt vor […]. Nimm alternativ current()[…]. Dann klappt es bei mir auch mit einem 1.0-Prozessor.

        Grüße,
        Thomas

        1. Habe es nun so probiert:

            <xsl:template match="ItemDeliveryInformation">
              <xsl:for-each select="current()[generate-id() = generate-id(key('group', concat(LineNumDeliveryNote, PackingSlipId, DeliveryDate))[1])]">
                <ItemDeliveryInformation>
                  <xsl:copy-of select="LineNumDeliveryNote"/>
                  <xsl:copy-of select="PackingSlipId"/>
                  <xsl:copy-of select="DeliveryDate"/>
                  <DeliveredQuantity>
                    <xsl:value-of select="format-number(sum(key('group', concat(LineNumDeliveryNote, PackingSlipId, DeliveryDate))/DeliveredQuantity), '#.00')"/>
                  </DeliveredQuantity>
                </ItemDeliveryInformation>
              </xsl:for-each>
            </xsl:template>
          

          Nun kommt folg. Error:

          Recoverable error Ambiguous rule match for /SALESINVOICE[1] Matches both "@* | node()" on line -1 of and "node()|@*" on line -1 of Recoverable error

          1. Hallo Julian,

            Nun kommt folg. Error:

            Recoverable error Ambiguous rule match for /SALESINVOICE[1] Matches both "@* | node()" on line -1 of and "node()|@*" on line -1 of Recoverable error

            Da es mit einem 1.0-Prozessor funktioniert, kann ich nur tippen, dass es an Deinem seltsamen Spezialprozessor liegt, der ja bereits Probleme mit Vergleichen hatte.

            Oder Du hast es wieder mit anderem XML-Code probiert, als der hier gezeigte. Ich erhalte das:

            <?xml version="1.0" encoding="UTF-8"?>
            <SALESINVOICE>
              <Interchange>
                <Recipient>1234</Recipient>
              </Interchange>
              <HeaderInformation>
                <OrigInvoiceNumber>1</OrigInvoiceNumber>
              </HeaderInformation>
              <LineInformation>
                <Item>
                  <LineNum>1</LineNum>
                  <ItemDeliveryInformation>
                    <LineNumDeliveryNote>1</LineNumDeliveryNote>
                    <PackingSlipId>PAC0029040</PackingSlipId>
                    <DeliveryDate>2021-01-08</DeliveryDate>
                    <DeliveredQuantity>14.00</DeliveredQuantity>
                  </ItemDeliveryInformation>
                  <ItemDeliveryInformation>
                    <LineNumDeliveryNote>1</LineNumDeliveryNote>
                    <PackingSlipId>PAC0029041</PackingSlipId>
                    <DeliveryDate>2021-01-08</DeliveryDate>
                    <DeliveredQuantity>4.00</DeliveredQuantity>
                  </ItemDeliveryInformation>
                </Item>
              </LineInformation>
            </SALESINVOICE>
            

            Grüße, Thomas

            1. nein sorrryyyyy viel peinlicher...

              Hab "<xsl:key name="group" match="ItemDeliveryInformation" use="concat(LineNumDeliveryNote, PackingSlipId, DeliveryDate)"/>" vergessen.

              Wie so oft 1000 dank für deine Mühe und Hilfe!!!!

              LG

            2. vl. kannst du mir nochmals kurz helfen.

              Hab in meinem bestehenden schon folg. enthalten:

              <xsl:key name="packing_slip" match="ItemDeliveryInformation" use="concat(LineNumDeliveryNote, '|', PackingSlipId, '|', DeliveryDate, '|', DeliveredQuantity, '|', RecId_InventTrans)"/>
              
              <xsl:template match="ItemDeliveryInformation[generate-id() != generate-id(key('packing_slip', concat(LineNumDeliveryNote, '|', PackingSlipId, '|', DeliveryDate, '|', DeliveredQuantity, '|', RecId_InventTrans))[1])]" />
              

              Wie kann ich das jetzt mit deinem Code kombinieren? Getrennt (einzeln) funktioniert alles.

              1. Hallo Julian,

                wenn ich beide Codezeilen in das letzte Beispiel einfüge, bleibt alles erhalten.

                Grüße,
                Thomas

                1. sorry, ich versuchs anders zu erklären. Wenn ich dafür ein neuen Eintrag im Forum erstellen soll, bitte um Info. :)

                  In meinem XSLT wird dieser Eintrag verwendet um Duplikate zu entfernen. -> Der Knoten ItemDeliveryInformation wird vervielfacht ausgegeben.

                  Und mit deiner Lösung der Berechnung im ItemDeliveryInformation zählt er jede DeliveredQuantity aus ItemDeliveryInformation, obwohl wir davor eigentlich die Duplikate gelöscht hätten.

                  Verstehst du wie ich meine?

                  Ansonsten würde ich das XML zur Verfügung stellen, worin sich noch die vervielfachung des ItemDeliveryInformations befindet.

                  LG Julian

                  1. Hallo Julian,

                    In meinem XSLT wird dieser Eintrag verwendet um Duplikate zu entfernen. -> Der Knoten ItemDeliveryInformation wird vervielfacht ausgegeben.

                    Und mit deiner Lösung der Berechnung im ItemDeliveryInformation zählt er jede DeliveredQuantity aus ItemDeliveryInformation, obwohl wir davor eigentlich die Duplikate gelöscht hätten.

                    Verstehst du wie ich meine?

                    Die Duplikate verschwinden ja nicht aus dem Eingabebaum, sondern erst im Ausgabebaum.

                    Ab 2.0 kann man XML-Fragmente erzeugen und diese dann auf ihren Teilbäumen weiterverarbeiten. Dort hätte man auch mit fn:distinct-values() mehr Möglichkeiten.

                    Insofern bietet sich bei 1.0 eher eine mehrstufige Transformation an.

                    Grüße,
                    Thomas

                    1. das dacht ich mir, dass mein Anliegen wieder einmal etwas naja "spannend" und aufwändig ist.

                      Ich hab hierfür sicherheitshalber einen neuen Beitrag eröffnet, darf ich dich nochmals um deine Hilfe bitten?

                      LG Julian

                    2. Ist das überhaupt möglich, meinen Fall zu lösen? Bräuchte bitte dringend eine Lösung, wenn das überhaupt machbar ist.

                      danke danke

                      lg Julian

                2. siehe bitte: https://forum.selfhtml.org/self/2021/feb/04/xslt-1-0-zwei-abfragen-kombinieren/1783595#m1783595