xml - Accumulating values in an array/list (XSL 2.0) -


i have requirement need accumulate values in array/list. not able populate values in array correctly different packed items.please help.

the requirement every container, check every packed item, if quantity (in current container ->packed item) equal "total" element in of preceding siblings. if yes; total= quantity
else; total=total+quantity //total 0

this process has repeated different packed items. packed item identified uniquely itemid parameter in input xml.

input xml

<?xml version="1.0" encoding="utf-8"?> <shipment xmlns="http://www.example.org">   <container>     <containerid>c1</containerid>     <packeditem>       <itemid>a123</itemid>       <quantity>4</quantity>       <total>0</total>     </packeditem>     <packeditem>       <itemid>a123</itemid>       <quantity>4</quantity>       <total>0</total>     </packeditem>     <packeditem>       <itemid>a111</itemid>       <quantity>4</quantity>       <total>0</total>     </packeditem>     <packeditem>       <itemid>a111</itemid>       <quantity>2</quantity>       <total>0</total>     </packeditem>   </container>   <container>     <containerid>c2</containerid>     <packeditem>       <itemid>a123</itemid>       <quantity>4</quantity>       <total>0</total>     </packeditem>     <packeditem>       <itemid>a123</itemid>       <quantity>8</quantity>       <total>0</total>     </packeditem>     <packeditem>       <itemid>a123</itemid>       <quantity>6</quantity>       <total>0</total>     </packeditem>     <packeditem>       <itemid>a111</itemid>       <quantity>6</quantity>       <total>0</total>     </packeditem>     <packeditem>       <itemid>a111</itemid>       <quantity>5</quantity>       <total>0</total>     </packeditem>     <packeditem>       <itemid>a111</itemid>       <quantity>2</quantity>       <total>0</total>     </packeditem>   </container>   <container>     <containerid>c3</containerid>     <packeditem>       <itemid>a123</itemid>       <quantity>3</quantity>       <total>0</total>     </packeditem>     <packeditem>       <itemid>a123</itemid>       <quantity>3</quantity>       <total>0</total>     </packeditem>     <packeditem>       <itemid>a123</itemid>       <quantity>2</quantity>       <total>0</total>     </packeditem>      <packeditem>       <itemid>a111</itemid>       <quantity>2</quantity>       <total>0</total>     </packeditem>      <packeditem>       <itemid>a111</itemid>       <quantity>2</quantity>       <total>0</total>     </packeditem>   </container> </shipment> 

output xml

<?xml version="1.0" encoding="utf-8"?> <shipment xmlns="http://www.example.org">   <container>     <containerid>c1</containerid>     <packeditem>       <itemid>a123</itemid>       <quantity>4</quantity>       <total>8</total>     </packeditem>     <packeditem>       <itemid>a123</itemid>       <quantity>4</quantity>       <total>8</total>     </packeditem>     <packeditem>       <itemid>a111</itemid>       <quantity>4</quantity>       <total>6</total>     </packeditem>     <packeditem>       <itemid>a111</itemid>       <quantity>2</quantity>       <total>6</total>     </packeditem>   </container>   <container>     <containerid>c2</containerid>     <packeditem>       <itemid>a123</itemid>       <quantity>4</quantity>       <total>10</total>     </packeditem>     <packeditem>       <itemid>a123</itemid>       <quantity>8</quantity>       <total>8</total>     </packeditem>     <packeditem>       <itemid>a123</itemid>       <quantity>6</quantity>       <total>10</total>     </packeditem>     <packeditem>       <itemid>a111</itemid>       <quantity>6</quantity>       <total>6</total>     </packeditem>     <packeditem>       <itemid>a111</itemid>       <quantity>5</quantity>       <total>7</total>     </packeditem>     <packeditem>       <itemid>a111</itemid>       <quantity>2</quantity>       <total>7</total>     </packeditem>   </container>   <container>     <containerid>c3</containerid>     <packeditem>       <itemid>a123</itemid>       <quantity>3</quantity>       <total>8</total>     </packeditem>     <packeditem>       <itemid>a123</itemid>       <quantity>3</quantity>       <total>8</total>     </packeditem>     <packeditem>       <itemid>a123</itemid>       <quantity>2</quantity>       <total>8</total>     </packeditem>   </container>    <packeditem>       <itemid>a111</itemid>       <quantity>2</quantity>       <total>4</total>     </packeditem>      <packeditem>       <itemid>a111</itemid>       <quantity>2</quantity>       <total>4</total>     </packeditem> </shipment> 

applied sample xml, means:

we have compare quantity in every packeditem each of preceding siblings "total" value. if quantity not equal of precding totals consider parameter form total particular packeditem in container. packeditems identified based on itemid.

for example: if see first container , value of total first container packeditem1 (itemid=a123) 8 (sum both quantites there no preceding siblings). second packed item (itemid=a111) value of total 6 (as there no preceding siblings). should have 2 records in our array a123 -> 8 , a111->6

for second container, first packeditem (a123) has first quantity 4. check if equal preceding siblings sum same item(which 8). since not equal considered total. moving further in second conatiner not consider 8 (in item a123) equal previous conatiners sum.the next packeditem (a123) has value 6. not equal preceding sibling (a123) sum considered total. have 4+6=10, forms sum packeditem a123 in second conatiner. on similar lines have process quantities packeditem a111. quantities 5 , 2 add form total 7.

this process repeated packed items in every container, updating total items quantity not equal sum of preceding sibling. pfb xslt (version 2.0) working on.

xslt

<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/xsl/transform"                  xmlns:ex="http://www.example.org"                 xmlns:ns0="http://www.example.org"                 xmlns:ns1="http://www.example.org" version="2.0">     <xsl:template match="/*">         <xsl:copy>             <xsl:apply-templates select="ex:container"/>         </xsl:copy>     </xsl:template>     <xsl:template match="node()|@*">         <xsl:param name="computed.totals"></xsl:param>         <xsl:param name="curr.total"></xsl:param>         <xsl:param name="itemid"></xsl:param>         <xsl:copy>             <xsl:apply-templates>                 <xsl:with-param name="computed.totals"                                 select="$computed.totals"></xsl:with-param>                 <xsl:with-param name="curr.total" select="$curr.total"></xsl:with-param>                 <xsl:with-param name="itemid" select="$itemid"/>             </xsl:apply-templates>         </xsl:copy>     </xsl:template>     <xsl:template match="ex:container">         <!-- trick initialize empty node-set, see http://lists.w3.org/archives/public/xsl-editors/2000julsep/0068.html -->         <xsl:param name="computed.totals" select="/@empty-node-set"/>         <ex:container>             <xsl:apply-templates>                 <xsl:with-param name="computed.totals"                                 select="$computed.totals"></xsl:with-param>             </xsl:apply-templates>         </ex:container>     </xsl:template>     <xsl:template match="ex:packeditem">         <xsl:param name="computed.totals"/>         <!-- process current total, taking accound totals of preceding siblings -->         <xsl:variable name="itemid" select="./ex:itemid"/>         <xsl:variable name="curr.total"                       select="sum(../ex:packeditem[./ex:itemid=$itemid]/ex:quantity[(($computed.totals)/mytotal[@itemid=$itemid]/@value != .) or not(($computed.totals)/*)])"></xsl:variable>         <!-- process current container elements -->         <xsl:copy>             <xsl:apply-templates>                 <xsl:with-param name="computed.totals"                                 select="$computed.totals"></xsl:with-param>                 <xsl:with-param name="curr.total" select="$curr.total"></xsl:with-param>                 <xsl:with-param name="itemid" select="$itemid"/>             </xsl:apply-templates>         </xsl:copy>         <!-- process next container, updated list of total computed -->         <xsl:apply-templates select="following-sibling::ex:container[1]">             <xsl:with-param name="computed.totals">                 <xsl:copy-of select="$computed.totals"/>                 <mytotal>                     <xsl:attribute name="containerid">                         <xsl:value-of select="ex:containerid"/>                     </xsl:attribute>                     <xsl:attribute name="value">                         <xsl:value-of select="$curr.total"/>                     </xsl:attribute>                     <xsl:attribute name="itemid">                         <xsl:value-of select="$itemid"/>                     </xsl:attribute>                 </mytotal>             </xsl:with-param>         </xsl:apply-templates>     </xsl:template>     <xsl:template match="*[starts-with(name(),'total')]">         <xsl:param name="computed.totals"></xsl:param>         <!-- store current total of container, used when processing total -->         <xsl:param name="curr.total"></xsl:param>         <xsl:param name="itemid"/>         <xsl:variable name="containerid" select="../../ns0:containerid"/>         <xsl:variable name="currentitemid" select="../ns0:itemid"/>         <xsl:variable name="quantity" select="../ns0:quantity"/>         <xsl:choose>             <xsl:when test="($computed.totals)/mytotal[@itemid=$currentitemid , @value = $quantity]">                 <xsl:copy-of select="$quantity"/>             </xsl:when>             <xsl:otherwise>                 <xsl:element name="total" namespace="http://www.example.org">                     <xsl:value-of select="$curr.total"/>                 </xsl:element>             </xsl:otherwise>         </xsl:choose>     </xsl:template> </xsl:stylesheet> 

here xslt 2.0 stylesheet trying implement computation of total values:

<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform"   xmlns:xs="http://www.w3.org/2001/xmlschema"   xmlns="http://www.example.org"   exclude-result-prefixes="xs"   xpath-default-namespace="http://www.example.org">  <xsl:strip-space elements="*"/> <xsl:output indent="yes"/>  <xsl:key name="cont-pack" match="container/packeditem" use="itemid"/>  <xsl:template match="@* | node()" mode="#all">   <xsl:copy>     <xsl:apply-templates select="@* | node()" mode="#current"/>   </xsl:copy> </xsl:template>  <xsl:template match="shipment">   <xsl:copy>     <xsl:apply-templates select="container[1]"/>   </xsl:copy> </xsl:template>  <xsl:template match="container">   <xsl:param name="computed" as="element(container)*" select="()"/>    <xsl:variable name="this-computed" as="element(container)">     <xsl:choose>       <xsl:when test="not($computed)">         <xsl:apply-templates select="." mode="compute-simple"/>       </xsl:when>       <xsl:otherwise>         <xsl:apply-templates select="." mode="compute">           <xsl:with-param name="prev" select="$computed[last()]" tunnel="yes"/>         </xsl:apply-templates>       </xsl:otherwise>     </xsl:choose>   </xsl:variable>      <xsl:choose>     <xsl:when test="not(following-sibling::container[1])">       <xsl:copy-of select="$computed, $this-computed"/>     </xsl:when>     <xsl:otherwise>       <xsl:apply-templates select="following-sibling::container[1]">         <xsl:with-param name="computed" select="$computed, $this-computed"/>       </xsl:apply-templates>     </xsl:otherwise>   </xsl:choose>  </xsl:template>  <xsl:template match="packeditem/total" mode="compute-simple">   <total changed="true">     <xsl:value-of select="sum(key('cont-pack', ../itemid, ancestor::container)/quantity)"/>   </total> </xsl:template>  <xsl:template match="packeditem/total" mode="compute">   <xsl:param name="prev" as="element(container)" tunnel="yes"/>   <xsl:variable name="prev-total" select="$prev/packeditem[itemid = current()/../itemid]/total[@changed = 'true']"/>   <total changed="{if ($prev-total = ../quantity) 'false' else 'true'}">     <xsl:value-of select="sum(key('cont-pack', ../itemid, ancestor::container)/quantity[not(. = $prev-total)])"/>   </total> </xsl:template>  </xsl:stylesheet> 

when applied saxon 9.6 input sample output

<shipment xmlns="http://www.example.org">    <container>       <containerid>c1</containerid>       <packeditem>          <itemid>a123</itemid>          <quantity>4</quantity>          <total changed="true">8</total>       </packeditem>       <packeditem>          <itemid>a123</itemid>          <quantity>4</quantity>          <total changed="true">8</total>       </packeditem>       <packeditem>          <itemid>a111</itemid>          <quantity>4</quantity>          <total changed="true">6</total>       </packeditem>       <packeditem>          <itemid>a111</itemid>          <quantity>2</quantity>          <total changed="true">6</total>       </packeditem>    </container>    <container>       <containerid>c2</containerid>       <packeditem>          <itemid>a123</itemid>          <quantity>4</quantity>          <total changed="true">10</total>       </packeditem>       <packeditem>          <itemid>a123</itemid>          <quantity>8</quantity>          <total changed="false">10</total>       </packeditem>       <packeditem>          <itemid>a123</itemid>          <quantity>6</quantity>          <total changed="true">10</total>       </packeditem>       <packeditem>          <itemid>a111</itemid>          <quantity>6</quantity>          <total changed="false">7</total>       </packeditem>       <packeditem>          <itemid>a111</itemid>          <quantity>5</quantity>          <total changed="true">7</total>       </packeditem>       <packeditem>          <itemid>a111</itemid>          <quantity>2</quantity>          <total changed="true">7</total>       </packeditem>    </container>    <container>       <containerid>c3</containerid>       <packeditem>          <itemid>a123</itemid>          <quantity>3</quantity>          <total changed="true">8</total>       </packeditem>       <packeditem>          <itemid>a123</itemid>          <quantity>3</quantity>          <total changed="true">8</total>       </packeditem>       <packeditem>          <itemid>a123</itemid>          <quantity>2</quantity>          <total changed="true">8</total>       </packeditem>       <packeditem>          <itemid>a111</itemid>          <quantity>2</quantity>          <total changed="true">4</total>       </packeditem>       <packeditem>          <itemid>a111</itemid>          <quantity>2</quantity>          <total changed="true">4</total>       </packeditem>    </container> </shipment> 

please check whether gives results totals looking for. realize attributes changed="true"/"false" don't belong final result if intermediary result fine in terms of total not difficult implement last processing step strips attributes:

<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform"   xmlns:xs="http://www.w3.org/2001/xmlschema"   xmlns="http://www.example.org"   exclude-result-prefixes="xs"   xpath-default-namespace="http://www.example.org">  <xsl:strip-space elements="*"/> <xsl:output indent="yes"/>  <xsl:key name="cont-pack" match="container/packeditem" use="itemid"/>  <xsl:template match="@* | node()" mode="#all">   <xsl:copy>     <xsl:apply-templates select="@* | node()" mode="#current"/>   </xsl:copy> </xsl:template>  <xsl:template match="shipment">   <xsl:copy>     <xsl:apply-templates select="container[1]"/>   </xsl:copy> </xsl:template>  <xsl:template match="container">   <xsl:param name="computed" as="element(container)*" select="()"/>    <xsl:variable name="this-computed" as="element(container)">     <xsl:choose>       <xsl:when test="not($computed)">         <xsl:apply-templates select="." mode="compute-simple"/>       </xsl:when>       <xsl:otherwise>         <xsl:apply-templates select="." mode="compute">           <xsl:with-param name="prev" select="$computed[last()]" tunnel="yes"/>         </xsl:apply-templates>       </xsl:otherwise>     </xsl:choose>   </xsl:variable>      <xsl:choose>     <xsl:when test="not(following-sibling::container[1])">       <xsl:apply-templates select="$computed, $this-computed" mode="strip"/>     </xsl:when>     <xsl:otherwise>       <xsl:apply-templates select="following-sibling::container[1]">         <xsl:with-param name="computed" select="$computed, $this-computed"/>       </xsl:apply-templates>     </xsl:otherwise>   </xsl:choose>  </xsl:template>  <xsl:template match="packeditem/total" mode="compute-simple">   <total changed="true">     <xsl:value-of select="sum(key('cont-pack', ../itemid, ancestor::container)/quantity)"/>   </total> </xsl:template>  <xsl:template match="packeditem/total" mode="compute">   <xsl:param name="prev" as="element(container)" tunnel="yes"/>   <xsl:variable name="prev-total" select="$prev/packeditem[itemid = current()/../itemid]/total[@changed = 'true']"/>   <total changed="{if ($prev-total = ../quantity) 'false' else 'true'}">     <xsl:value-of select="sum(key('cont-pack', ../itemid, ancestor::container)/quantity[not(. = $prev-total)])"/>   </total> </xsl:template>  <xsl:template match="packeditem/total/@changed" mode="strip"/>  </xsl:stylesheet> 

Comments

Popular posts from this blog

angularjs - ADAL JS Angular- WebAPI add a new role claim to the token -

php - CakePHP HttpSockets send array of paramms -

node.js - Using Node without global install -