Smart questions
Smart answers
Smart people
INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Member Login




Remember Me
Forgot Password?
Join Us!

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips now!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!

Join Tek-Tips
*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.
Jobs from Indeed

Link To This Forum!

Partner Button
Add Stickiness To Your Site By Linking To This Professionally Managed Technical Forum.
Just copy and paste the
code below into your site.

select the group of rows based on the three XML fields and with these Helpful Member! 

ccpuser (Programmer) (OP)
21 Oct 10 21:58
I would like to group based on fields of row element (combination of StackNumber,BlockNumber and LocationCode) and select only higher BookVersion (BookVersion) based rows in particular group(combination of StackNumber,BlockNumber and LocationCode) and also to select the rows of DeliveryMode with the value as TRANSIT.

Here is the input document

<?xml version="1.0"?>
<Output>
<row>
<StackNumber>19</StackNumber>
<BlockNumber>61001</BlockNumber>
<DeliveryMode>TRANSIT</DeliveryMode>
<LocationCode>MON</LocationCode>
<BookVersion>03</BookVersion>
<StoreNumber>1010</StoreNumber>

</row>
<row>
<StackNumber>20</StackNumber>
<BlockNumber>61001</BlockNumber>
<DeliveryMode>TRANSIT</DeliveryMode>
<LocationCode>MON</LocationCode>
<BookVersion>01</BookVersion>
<StoreNumber>1011</StoreNumber>
</row>
<row>
<StackNumber>20</StackNumber>
<BlockNumber>61001</BlockNumber>
<DeliveryMode>TRANSIT</DeliveryMode>
<LocationCode>MON</LocationCode>
<BookVersion>02</BookVersion>
<StoreNumber>1013</StoreNumber>
</row>
<row>
<StackNumber>21</StackNumber>
<BlockNumber>61001</BlockNumber>
<DeliveryMode>RECVD</DeliveryMode>
<LocationCode>MON</LocationCode>
<BookVersion>03</BookVersion>
<StoreNumber>1022</StoreNumber>
</row>
<row>
<StackNumber>21</StackNumber>
<BlockNumber>61001</BlockNumber>
<DeliveryMode>TRANSIT</DeliveryMode>
<LocationCode>MON</LocationCode>
<BookVersion>03</BookVersion>
<StoreNumber>1022</StoreNumber>
</row>
<row>
<StackNumber>22</StackNumber>
<BlockNumber>15098</BlockNumber>
<DeliveryMode>TRANSIT</DeliveryMode>
<LocationCode>MON</LocationCode>
<BookVersion>01</BookVersion>
<StoreNumber>1010</StoreNumber>
</row>
<row>
<StackNumber>22</StackNumber>
<BlockNumber>22456</BlockNumber>
<DeliveryMode>TRANSIT</DeliveryMode>
<LocationCode>MON</LocationCode>
<BookVersion>02</BookVersion>
<StoreNumber>1011</StoreNumber>
</row>
<row>
<StackNumber>22</StackNumber>
<BlockNumber>22456</BlockNumber>
<DeliveryMode>TRANSIT</DeliveryMode>
<LocationCode>MON</LocationCode>
<BookVersion>03</BookVersion>
<StoreNumber>1012</StoreNumber>
</row>
<row>
<StackNumber>22</StackNumber>
<BlockNumber>22456</BlockNumber>
<DeliveryMode>RECVD</DeliveryMode>
<LocationCode>MON</LocationCode>
<BookVersion>02</BookVersion>
<StoreNumber>1021</StoreNumber>
</row>
</Output>
XSL (using saxon 9 parser) that I wrote:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="xml" indent="yes"/>

<xsl:key name="transitGroup" match="row" use="concat(StackNumber,BlockNumber,LocationCode)"/>

<xsl:template match="/">
<Output>
<xsl:for-each select="//row[generate-id(.) = generate-id(key('transitGroup',concat(StackNumber,BlockNumb er,LocationCode))[1])]">
<xsl:variable name="BookVersion" select="key('transitGroup',concat(StackNumber,Bloc kNumber,LocationCode))/BookVersion"/>
<xsl:if test="DeliveryMode = 'TRANSIT'">
<row>
<StackNumber>
<xsl:value-of select="StackNumber"/>
</StackNumber>
<BlockNumber>
<xsl:value-of select="BlockNumber"/>
</BlockNumber>
<LocationCode>
<xsl:value-of select="LocationCode"/>
</LocationCode>
<StoreNumber>
<xsl:value-of select="StoreNumber"/>
</StoreNumber>

<xsl:for-each select="$BookVersion">

<xsl:sort select="." data-type="number" order="descending"/>

<xsl:if test="position()=1">

<BookVersion>
<xsl:value-of select="."/>
</BookVersion>
</xsl:if>
</xsl:for-each>
</row>
</xsl:if>
</xsl:for-each>
</Output>
</xsl:template>
</xsl:stylesheet>


I wrote this above one but can't figure out to select correct store number based on greater value based element 'BookVersion' in each group.

example group must be printed like this .

<row>
<StackNumber>20</StackNumber>
<BlockNumber>61001</BlockNumber>
<LocationCode>MON</LocationCode>
<StoreNumber>1013</StoreNumber>
<BookVersion>02</BookVersion>
</row>

I'm getting wrong store number here for a particular selected group. I'm struck to proceed further here, I will appreciate if some body can lead me the way to write correct it in this XSL.
Helpful Member!  tsuji (TechnicalUser)
22 Oct 10 2:08
[0] I think this will be clearer with each construction reflecting a special line of thinking to get to the result.

<?xml version="1.0" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" encoding="utf-8" />
<xsl:key name="transitGroup" match="row[DeliveryMode='TRANSIT']" use="concat(StackNumber,BlockNumber,LocationCode)"/>

<xsl:template match="/">
  <xsl:apply-templates select="Output" />
</xsl:template>

<xsl:template match="Output">
  <Output>
    <xsl:apply-templates select="row[DeliveryMode='TRANSIT']" mode="special"/>
  </Output>
</xsl:template>

<xsl:template match="row[DeliveryMode='TRANSIT']" mode="special">
  <xsl:if test="generate-id(.)=generate-id(key('transitGroup', concat(StackNumber,BlockNumber,LocationCode))[1])">
    <xsl:for-each select="key('transitGroup', concat(StackNumber,BlockNumber,LocationCode))">
      <xsl:sort select="BookVersion" data-type="number" order="descending" />
      <xsl:choose>
        <xsl:when test="position() = 1">
          <xsl:call-template name="display" />
        </xsl:when>
        <xsl:otherwise>
          <!-- do nothing -->
        </xsl:otherwise>
      </xsl:choose>
    </xsl:for-each>
  </xsl:if>
</xsl:template>

<xsl:template name="display">
  <row>
    <StackNumber>
      <xsl:value-of select="StackNumber"/>
    </StackNumber>
    <BlockNumber>
      <xsl:value-of select="BlockNumber"/>
    </BlockNumber>
    <LocationCode>
      <xsl:value-of select="LocationCode"/>
    </LocationCode>
    <StoreNumber>
      <xsl:value-of select="StoreNumber"/>
    </StoreNumber>
    <BookVersion>
      <xsl:value-of select="BookVersion" />
    </BookVersion>
  </row>
</xsl:template>

</xsl:stylesheet>

[1] The problem with your script, apart from being loose in the construction at places, is that the BookVersion suddenly pop up like a block-apart...

[2] Just a side-note. If you think you've got adequate help, maybe you can put up a note at the "other" forum so that the conduct is more professional. But I won't insist!
ccpuser (Programmer) (OP)
22 Oct 10 8:24
Another solution for this problem based on on XSL version 2.0 feature:

<?xml version="1.0" encoding="US-ASCII"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                exclude-result-prefixes="xsd"
                version="2.0">

<xsl:output indent="yes"/>

<xsl:template match="/">
  <Output>
    <xsl:for-each-group select="*/row[DeliveryMode='TRANSIT']"
                        group-by="concat(StackNumber,'&#xd;',
                                         BlockNumber,'&#xd;',LocationCode)">
      <xsl:for-each select="current-group()
                            [xsd:decimal(BookVersion)=
                            max(current-group()/BookVersion/xsd:decimal(.))]
                            [1]">
        <row>
          <xsl:copy-of select="* except DeliveryMode"/>
        </row>
      </xsl:for-each>
    </xsl:for-each-group>
  </Output>
</xsl:template>

</xsl:stylesheet>
tsuji (TechnicalUser)
22 Oct 10 10:39
xslt 2.0 solutions are sure possible and thanks for the post-back of one.

Reply To This Thread

Posting in the Tek-Tips forums is a member-only feature.

Click Here to join Tek-Tips and talk with other members!

Back To Forum

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close