XSLT newbie
XSLT newbie

Reputation: 31

XSLT total per unique value

Apologies. I asked a question just a few days ago and it was already answered by Sir michael.hor257k. I have a new requirement though. The TOTAL field needs to count the sgtin fields per unique value like the sample below.

   <xsl:template match="/*">
      <MESSAGE>
          <PALLET>
            <xsl:for-each select="//*[local-name()='ObjectEvent'][substring(epcList/epc,1,16) = 'urn:epc:id:sgtin']">
              <MATERIAL>
                <BOX>
                  <TOTAL>
                    <xsl:value-of select="count(./epcList/epc[substring(.,1,16) = 'urn:epc:id:sgtin'])"/>
                  </TOTAL>
                  <xsl:for-each select="./epcList/epc[substring(.,1,16) = 'urn:epc:id:sgtin']">
                    <SERIES>
                      <ITEM>
                        <xsl:value-of select="substring-after(substring-after(.,'.'),'.')"/>
                      </ITEM>
                    </SERIES>
                </BOX>
              </MATERIAL>
          </PALLET>
      </MESSAGE>

This is a sample input file:

<?xml version="1.0" encoding="UTF-8"?>
<n0:EPCISDocument xmlns:n0="urn:epcglobal:epcis:xsd:1" xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" schemaVersion="1.1">
  <ObjectEvent>
    <epcList>
      <epc>urn:epc:id:sgtin:999999999.0000.0000000001</epc>
      <epc>urn:epc:id:sgtin:999999999.0000.0000000002</epc>
    </epcList>
    <Extension>
      <obj>
        <BATCH>ABCD_00</BATCH>
      </obj>
    </Extension>
  </ObjectEvent>
  <ObjectEvent>
    <epcList>
      <epc>urn:epc:id:sgtin:999999999.0000.0000000003</epc>
      <epc>urn:epc:id:sgtin:999999999.0000.0000000004</epc>
      <epc>urn:epc:id:sgtin:999999999.0000.0000000005</epc>
    </epcList>
    <Extension>
      <obj>
        <BATCH>ABCD_00</BATCH>
      </obj>
    </Extension>
  </ObjectEvent>
  <ObjectEvent>
    <epcList>
      <epc>urn:epc:id:sgtin:999999999.1111.0000000006</epc>
      <epc>urn:epc:id:sgtin:999999999.1111.0000000007</epc>
      <epc>urn:epc:id:sgtin:999999999.1111.0000000008</epc>
    </epcList>
    <Extension>
      <obj>
        <BATCH>EFGH_11</BATCH>
      </obj>
    </Extension>
  </ObjectEvent>
  <ObjectEvent>
    <epcList>
      <epc>urn:epc:id:sgtin:999999999.2222.0000000009</epc>
    </epcList>
    <Extension>
      <obj>
        <BATCH>IJKL_22</BATCH>
      </obj>
    </Extension>
  </ObjectEvent>
</n0:EPCISDocument>

The TSERIES will be counted per GTIN (0000, 1111, 2222).

The expected should be:

<?xml version="1.0" encoding="UTF-8"?>
<MESSAGE>
  <PALLET>
    <MATERIAL>
      <BOX>
        <TOTAL>5</TOTAL>
        <SERIES>
          <ITEM>0000000001</ITEM>
        </SERIES>
        <SERIES>
          <ITEM>0000000002</ITEM>
        </SERIES>
      </BOX>
    </MATERIAL>
    <MATERIAL>
      <BOX>
        <TOTAL>5</TOTAL>
        <SERIES>
          <ITEM>0000000003</ITEM>
        </SERIES>
        <SERIES>
          <ITEM>0000000004</ITEM>
        </SERIES>
        <SERIES>
          <ITEM>0000000005</ITEM>
        </SERIES>
      </BOX>
    </MATERIAL>
    <MATERIAL>
      <BOX>
        <TOTAL>3</TOTAL>
        <SERIES>
          <ITEM>0000000006</ITEM>
        </SERIES>
        <SERIES>
          <ITEM>0000000007</ITEM>
        </SERIES>
        <SERIES>
          <ITEM>0000000008</ITEM>
        </SERIES>
      </BOX>
    </MATERIAL>
    <MATERIAL>
      <BOX>
        <TOTAL>1</TOTAL>
        <SERIES>
          <ITEM>0000000009</ITEM>
        </SERIES>
      </BOX>
    </MATERIAL>
  </PALLET>
</MESSAGE>

Is this possible Masters?

edit: I'm not sure if this can help. I edited the source payload to add BATCH field. that is unique per GTIN. Can it be used for the TSERIES total?

Upvotes: 0

Views: 63

Answers (1)

michael.hor257k
michael.hor257k

Reputation: 116982

As I said in the comment, this is a grouping problem and the preferred solution in XSLT 1.0 is to use the Muenchian grouping method:

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:key name="batch" match="ObjectEvent" use="Extension/obj/BATCH" />

<xsl:template match="/*">
    <MESSAGE>
        <PALLET>
            <!-- for each distinct batch -->
            <xsl:for-each select="ObjectEvent[count(. | key('batch', Extension/obj/BATCH)[1]) = 1]">
                <xsl:variable name="current-group" select="key('batch', Extension/obj/BATCH)" />
                <xsl:variable name="group-total" select="count($current-group/epcList/epc)"/>
                <!-- for each ObjectEvent in this batch -->
                <xsl:for-each select="$current-group">
                    <MATERIAL>
                        <BOX>
                            <TOTAL>
                                 <xsl:value-of select="$group-total"/>
                            </TOTAL>
                            <xsl:for-each select="epcList/epc">
                                <SERIES>
                                    <ITEM>
                                        <xsl:value-of select="substring(., 33)"/>
                                    </ITEM>
                                </SERIES>
                            </xsl:for-each> 
                        </BOX>
                    </MATERIAL>
                </xsl:for-each> 
            </xsl:for-each> 
        </PALLET>
    </MESSAGE>
</xsl:template>

</xsl:stylesheet>

Note that this assumes all SGTINs have the same number of characters.

Upvotes: 1

Related Questions