I need to do a check: If "ITEM.ITEM_NUMBER_IN" is more than one time with the same value. -> Like here: 315024 is twice
We have to sum "ITEM.QUANTITY_12" and create one line instead of two. -> But note, it could be, that the same "ITEM.ITEM_NUMBER_IN" is more than two times available.
XML:
<?xml version="1.0" encoding="ISO-8859-1"?>
<SEEDESADV>
<SEE_AG COPYRIGHT="SEEBURGER AG" CREATION_DATE="2007-05-09" MESSAGE="SEEDESADV_V3_0" MAPPING="RECA_AT_DESADV_D96A_IN" VERSION="1.0.74"/>
<CNT>
<IC>
<REF_ON>00120925</REF_ON>
</IC>
<GRP>
<MSG>
<ME>
<MESSAGE_NUMBER>274103076</MESSAGE_NUMBER>
</ME>
<ASN>
<DATE>
<QUALIFIER>17</QUALIFIER>
<DATE>20220124</DATE>
</DATE>
<TXT>
<QUALIFIER>QUC</QUALIFIER>
<TEXT_LINE>ADD:BY#BY</TEXT_LINE>
</TXT>
<ITEM>
<LINE_ITEM_NUMBER>10</LINE_ITEM_NUMBER>
<ITEM_NUMBER_IN>323656</ITEM_NUMBER_IN>
<QUANTITY_12>1000</QUANTITY_12>
<QUANTITY_UNIT>PCE</QUANTITY_UNIT>
</ITEM>
<ITEM>
<LINE_ITEM_NUMBER>20</LINE_ITEM_NUMBER>
<ITEM_NUMBER_IN>315024</ITEM_NUMBER_IN>
<QUANTITY_12>6000</QUANTITY_12>
<QUANTITY_UNIT>PCE</QUANTITY_UNIT>
</ITEM>
<ITEM>
<LINE_ITEM_NUMBER>30</LINE_ITEM_NUMBER>
<ITEM_NUMBER_IN>315024</ITEM_NUMBER_IN>
<QUANTITY_12>5000</QUANTITY_12>
<QUANTITY_UNIT>PCE</QUANTITY_UNIT>
</ITEM>
</ASN>
</MSG>
</GRP>
</CNT>
</SEEDESADV>
XSLT:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="group" match="ITEM" use="concat(ITEM_NUMBER_IN, QUANTITY_UNIT)"/>
<xsl:template match="ITEM">
<xsl:for-each select=".[generate-id() = generate-id(key('group', concat(ITEM_NUMBER_IN, QUANTITY_UNIT))[1])]">
<xsl:choose>
<xsl:when test="not.[generate-id() = generate-id(key('group', concat(ITEM_NUMBER_IN, QUANTITY_UNIT))[1])]">
<ITEM>
<xsl:copy-of select="LINE_ITEM_NUMBER"/>
<xsl:copy-of select="ITEM_NUMBER_IN"/>
<QUANTITY_12>
<xsl:value-of select="format-number(sum(key('group', concat(ITEM_NUMBER_IN, QUANTITY_UNIT))/QUANTITY_12), '#')"/>
</QUANTITY_12>
<xsl:copy-of select="QUANTITY_UNIT"/>
</ITEM>
</xsl:when>
<xsl:otherwise>
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</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()='']"/>
<!-- delete empty nodes -->
</xsl:stylesheet>
Correct:
<?xml version="1.0" encoding="ISO-8859-1"?>
<SEEDESADV>
<SEE_AG COPYRIGHT="SEEBURGER AG" CREATION_DATE="2007-05-09" MESSAGE="SEEDESADV_V3_0" MAPPING="RECA_AT_DESADV_D96A_IN" VERSION="1.0.74"/>
<CNT>
<IC>
<REF_ON>00120925</REF_ON>
</IC>
<GRP>
<MSG>
<ME>
<MESSAGE_NUMBER>274103076</MESSAGE_NUMBER>
</ME>
<ASN>
<DATE>
<QUALIFIER>17</QUALIFIER>
<DATE>20220124</DATE>
</DATE>
<TXT>
<QUALIFIER>QUC</QUALIFIER>
<TEXT_LINE>ADD:BY#BY</TEXT_LINE>
</TXT>
<ITEM>
<LINE_ITEM_NUMBER>10</LINE_ITEM_NUMBER>
<ITEM_NUMBER_IN>323656</ITEM_NUMBER_IN>
<QUANTITY_12>1000</QUANTITY_12>
<QUANTITY_UNIT>PCE</QUANTITY_UNIT>
</ITEM>
<ITEM>
<LINE_ITEM_NUMBER>20</LINE_ITEM_NUMBER>
<ITEM_NUMBER_IN>315024</ITEM_NUMBER_IN>
<QUANTITY_12>11000</QUANTITY_12>
<QUANTITY_UNIT>PCE</QUANTITY_UNIT>
</ITEM>
</ASN>
</MSG>
</GRP>
</CNT>
</SEEDESADV>
Please let me know, if everything is clear.
Thanks for you help.
Best regards Julian
CodePudding user response:
You need to do the grouping from the context of the parent (or ancestor) of the nodes being grouped.
Try it along these lines:
XSLT 1.0
<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:key name="item" match="ITEM" use="ITEM_NUMBER_IN"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ASN">
<xsl:apply-templates select="DATE | TXT"/>
<xsl:for-each select="ITEM[generate-id() = generate-id(key('item', ITEM_NUMBER_IN)[1])]">
<ITEM>
<xsl:copy-of select="LINE_ITEM_NUMBER | ITEM_NUMBER_IN"/>
<QUANTITY_12>
<xsl:value-of select="sum(key('item', ITEM_NUMBER_IN)/QUANTITY_12)"/>
</QUANTITY_12>
<xsl:copy-of select="QUANTITY_UNIT"/>
</ITEM>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
CodePudding user response:
I´ve done it this way:
<xsl:key name="item" match="ITEM" use="ITEM_NUMBER_IN"/>
<xsl:template match="ASN">
<xsl:for-each select="//ITEM[generate-id() = generate-id(key('item', ITEM_NUMBER_IN)[1])]">
<xsl:choose>
<xsl:when test="//ITEM[generate-id() = generate-id(key('item', ITEM_NUMBER_IN)[1])]">
<ITEM>
<xsl:copy-of select="LINE_ITEM_NUMBER"/>
<xsl:copy-of select="ITEM_DESCRIPTION"/>
<xsl:copy-of select="ITEM_NUMBER_IN"/>
<xsl:copy-of select="ITEM_NUMBER_SA"/>
<QUANTITY_12>
<xsl:value-of select="sum(key('item', ITEM_NUMBER_IN)/QUANTITY_12)"/>
</QUANTITY_12>
<xsl:copy-of select="QUANTITY_UNIT"/>
</ITEM>
</xsl:when>
<xsl:otherwise>
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>