Wrox Programmer Forums
Go Back   Wrox Programmer Forums > XML > XSLT
|
XSLT General questions and answers about XSLT. For issues strictly specific to the book XSLT 1.1 Programmers Reference, please post to that forum instead.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the XSLT section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old March 12th, 2009, 11:22 AM
Authorized User
 
Join Date: Feb 2009
Posts: 43
Thanks: 10
Thanked 0 Times in 0 Posts
Default Getting unique values from substring

Martin,

I'm sorry I am starting another thread with the same title. I can't post a reply to the other thread I started.

As requested My xml is below

Code:
  <Properties> 
       <Data>

   
  -     <Result>
   -       <PRList>          

   
           <PressRelease dcr="">
                <date>10/02/2008</date> 

               <title>Title</title> 

               <content></content>  

         </PressRelease>
      <PRList>
   </Result>
 </Data>
</Properties>
Please let me know if this is complete enough

Once again my xsl is as follows....

Code:
<xsl:for-each select="$dcr">
<!--xsl:for-each select="$dcr[generate-id() = generate-id(key('by-month', substring(date,1,2))[1])]"-->
 
            <!--xsl:sort select="substring(date,1,2)" order="ascending"/-->
            <xsl:variable name="yearn" select="substring(date,7,4)"/>
            <xsl:variable name="monthn" select="substring(date,1,2)"/>

            <!--xsl:value-of select="$currentYear"/><xsl:value-of select="$yearn"/><br/-->
            <xsl:choose> 
            <xsl:when test="$currentYear = $yearn">
             
            
            <tr>
              <td align="top" valign="middle">
               <!--b><xsl:value-of select="substring(date,1,2)"/></b><br/-->
               <a href="$PAGE_LINK[/press-releases/detail]dcr={@dcr}"><xsl:value-of select="title"/></a><br/>
               </td>
            </tr>
            </xsl:when>
            </xsl:choose> 
            </xsl:for-each>
I commented out
Code:
<!--xsl:for-each select="$dcr[generate-id() = generate-id(key('by-month', substring(date,1,2))[1])]"-->
for now.


Once again my goal is

Month i.e. Janaury
Press release 1
Press release 2

Date


Month i.e.February
Press release 1
Press release 2

Date


Thanks.
 
Old March 12th, 2009, 12:52 PM
Friend of Wrox
 
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
Default

Well you need to use Muenchian grouping in XSLT 1.0 to group on your month component.
As for your code samples, no, that does not help us to tell you where it goes wrong, the input markup sample is not even well-formed XML and if you want help with grouping then there should be enough data to at least populate a few groups. And that stylesheet would need to show how the key is defined, how the variables are set up. So if you want help in explaining why your stylesheet does not work as expected then post minimal but complete samples that we can run without any need for editing them first.

In the meantime, here is some working sample. I produced the following XML input sample:
Code:
<Properties> 
  <Data>
    <Result>
      <PRList>          
        <PressRelease dcr="">
          <date>10/02/2008</date> 
          <title>release 1</title> 
          <content></content>  
        </PressRelease>
        <PressRelease dcr="">
          <date>10/03/2008</date> 
          <title>release 2</title> 
          <content></content>  
        </PressRelease>
        <PressRelease dcr="">
          <date>01/03/2008</date> 
          <title>release 3</title> 
          <content></content>  
        </PressRelease>
        <PressRelease dcr="">
          <date>01/12/2008</date> 
          <title>release 4</title> 
          <content></content>  
        </PressRelease>
      </PRList>
    </Result>
  </Data>
</Properties>
then wrote the following stylesheet
Code:
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:data="http://example.com/2009/mh"
  exclude-result-prefixes="data"
  version="1.0">
  
  <xsl:output method="text"/>
  
  <xsl:key name="by-month"
           match="PressRelease"
           use="substring-before(date, '/')"/>
  
  <data:data>
    <month number="01">January</month>
    <month number="02">February</month>
    <month number="03">March</month>
    <month number="04">April</month>
    <month number="05">May</month>
    <month number="06">June</month>
    <month number="07">July</month>
    <month number="08">August</month>
    <month number="09">September</month>
    <month number="10">October</month>
    <month number="11">November</month>
    <month number="12">December</month>
  </data:data>
  
  <xsl:template match="/">
    <xsl:for-each select="Properties/Data/Result/PRList/PressRelease[generate-id() = generate-id(key('by-month', substring-before(date, '/'))[1])]">
      <xsl:sort select="substring-before(date, '/')"/>
      <xsl:value-of select="document('')/xsl:stylesheet/data:data/month[@number = substring-before(current()/date, '/')]"/>
      <xsl:text>
</xsl:text>
      <xsl:for-each select="key('by-month', substring-before(date, '/'))/title">
        <xsl:value-of select="concat(., '
')"/>
      </xsl:for-each>
    </xsl:for-each>
  </xsl:template>

</xsl:stylesheet>
that when run with Saxon 6.5.5 produces the following output:

January
release 3
release 4
October
release 1
release 2


So that is grouped and sorted fine by the month component accessed using substring-before(date, '/').
__________________
Martin Honnen
Microsoft MVP (XML, Data Platform Development) 2005/04 - 2013/03
My blog
 
Old March 13th, 2009, 01:21 AM
Authorized User
 
Join Date: Feb 2009
Posts: 43
Thanks: 10
Thanked 0 Times in 0 Posts
Default

Thanks Martin. Sorry for being a pain.

The code you sent worked. I just have one problem. The xml I am working with contains data for different years e.g 2009, 2007 etc.

In the light of this, your currently code returns all the press releases per month i.e January regardless of the year, I also need to filter this by year.

I tried this with your code....

Code:
<xsl:for-each select="$dcr[generate-id() = generate-id(key('by-month', substring-before(date, '/'))[1])]">
                  <xsl:sort select="substring-before(date, '/')"/>                        
                     <tr>
                       <td align="top" valign="middle" class="MarkitBodyText">
                         <xsl:value-of select="substring-before(current()/date, '/')"/><br/>
                           <xsl:for-each select="key('by-month', substring-before(date, '/'))/title">
                             <xsl:if test="$currentYear = substring(date,7,4)"-->
                               <xsl:value-of select="concat(., '')"/><br/>
                             </xsl:if-->                             
                           </xsl:for-each>
                       </td>
                     </tr>
                </xsl:for-each>
But the if statement did not return any Press release titles, thus it is no filtering on the year portion of the date.

The variables are defined thus
Code:
<xsl:variable name="currentYear">
<xsl:choose>
 <xsl:when test="$year = ''">
  <xsl:value-of select="datetime:year()"/> 
</xsl:when>
<xsl:otherwise>
  <xsl:value-of select="$year"/>
</xsl:otherwise>
</xsl:choose> 
</xsl:variable> 


<xsl:variable name="yearn" select="substring(date,7,4)"/>

The ideas is that if no $year parameter is passed to this component, $currentYear is set to the current year, all the press releases for the current year and then pasred for display. That is the bit I can't get to work -

Thanks again
 
Old March 13th, 2009, 11:01 AM
Friend of Wrox
 
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
Default

If you have data in different years then the key needs to be adapted to include the year as well as the month.
So extending my earlier example we now have the example file as
Code:
<Properties> 
  <Data>
    <Result>
      <PRList>          
        <PressRelease dcr="">
          <date>10/02/2008</date> 
          <title>release 1</title> 
          <content></content>  
        </PressRelease>
        <PressRelease dcr="">
          <date>10/03/2008</date> 
          <title>release 2</title> 
          <content></content>  
        </PressRelease>
        <PressRelease dcr="">
          <date>01/03/2008</date> 
          <title>release 3</title> 
          <content></content>  
        </PressRelease>
        <PressRelease dcr="">
          <date>01/12/2008</date> 
          <title>release 4</title> 
          <content></content>  
        </PressRelease>
        
        <PressRelease dcr="">
          <date>09/02/2009</date> 
          <title>release 5</title> 
          <content></content>  
        </PressRelease>
        <PressRelease dcr="">
          <date>09/03/2009</date> 
          <title>release 6</title> 
          <content></content>  
        </PressRelease>
        <PressRelease dcr="">
          <date>01/03/2009</date> 
          <title>release 7</title> 
          <content></content>  
        </PressRelease>
        <PressRelease dcr="">
          <date>01/12/2009</date> 
          <title>release 8</title> 
          <content></content>  
        </PressRelease>
        
      </PRList>
    </Result>
  </Data>
</Properties>
then the stylesheet as follows:
Code:
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:data="http://example.com/2009/mh"
  xmlns:datetime="http://exslt.org/dates-and-times"
  exclude-result-prefixes="data datetime"
  version="1.0">
  
  <xsl:output method="text"/>
  
  <xsl:param name="yearParam" select="''"/>
  
  <xsl:variable name="year">
    <xsl:choose>
      <xsl:when test="$yearParam = ''">
        <xsl:value-of select="datetime:year()"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$yearParam"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>
           
  <xsl:key name="by-month"
           match="PressRelease"
           use="concat(substring-after(substring-after(date, '/'), '/'), '-', substring-before(date, '/'))"/>
  
  <data:data>
    <month number="01">January</month>
    <month number="02">February</month>
    <month number="03">March</month>
    <month number="04">April</month>
    <month number="05">May</month>
    <month number="06">June</month>
    <month number="07">July</month>
    <month number="08">August</month>
    <month number="09">September</month>
    <month number="10">October</month>
    <month number="11">November</month>
    <month number="12">December</month>
  </data:data>
  
  <xsl:template match="/">
    <xsl:value-of select="concat('Press releases in ', $year, ':
')"/>
    <xsl:for-each select="Properties/Data/Result/PRList/PressRelease[$year = substring-after(substring-after(date, '/'), '/')][generate-id() = generate-id(key('by-month', concat(substring-after(substring-after(date, '/'), '/'), '-', substring-before(date, '/')))[1])]">
      <xsl:sort select="substring-before(date, '/')"/>
      <xsl:value-of select="document('')/xsl:stylesheet/data:data/month[@number = substring-before(current()/date, '/')]"/>
      <xsl:text>
</xsl:text>
      <xsl:for-each select="key('by-month', concat(substring-after(substring-after(date, '/'), '/'), '-', substring-before(date, '/')))/title">
        <xsl:value-of select="concat(., '
')"/>
      </xsl:for-each>
    </xsl:for-each>
  </xsl:template>

</xsl:stylesheet>
When run against the sample input without setting the yearParam parameter the result with Saxon 6.5.5 is

Press releases in 2009:
January
release 7
release 8
September
release 5
release 6

when run with Saxon 6.5.5 when setting yearParam=2008 the result is as follows:

Press releases in 2008:
January
release 3
release 4
October
release 1
release 2
__________________
Martin Honnen
Microsoft MVP (XML, Data Platform Development) 2005/04 - 2013/03
My blog
 
Old March 13th, 2009, 12:37 PM
Authorized User
 
Join Date: Feb 2009
Posts: 43
Thanks: 10
Thanked 0 Times in 0 Posts
Default

Martin - thanks very much for the time you have taken to help.

Finally -one last question


I also need to display the date for every press release title

The code below <xsl:value-of select="$dcr/date"/> only returns the first date.
Code:
<xsl:for-each select="key('by-month', concat(substring-after(substring-after(date, '/'), '/'), '-', substring-before(date, '/')))/title">
                             <xsl:value-of select="concat(., '')"/><br/>
                             <xsl:value-of select="date"/> 
                           </xsl:for-each><br/>
Thanks again.
 
Old March 13th, 2009, 12:46 PM
Friend of Wrox
 
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
Default

In the for-each you select the title element so I am astonished that you say it outputs the first date. Given your sample the title element is a sibling of the date element so your for-each should not find any date at all.
Try whether
Code:
<xsl:for-each select="key('by-month', concat(substring-after(substring-after(date, '/'), '/'), '-', substring-before(date, '/')))">
      <xsl:value-of select="title"/><br/>
      <xsl:value-of select="date"/> 
</xsl:for-each>
gives you what you are looking for. If not then you will need to post a relevant sample of the XML you have again.
__________________
Martin Honnen
Microsoft MVP (XML, Data Platform Development) 2005/04 - 2013/03
My blog
The Following User Says Thank You to Martin Honnen For This Useful Post:
rabs (March 13th, 2009)
 
Old March 13th, 2009, 03:10 PM
Authorized User
 
Join Date: Feb 2009
Posts: 43
Thanks: 10
Thanked 0 Times in 0 Posts
Default

Thanks Martin - that was exactly what I wanted.





Similar Threads
Thread Thread Starter Forum Replies Last Post
Getting unique values from substring rabs XSLT 16 March 5th, 2009 01:39 PM
How to Generate Unique values for IDs mphare XSLT 7 November 6th, 2008 12:20 PM
substring in c# sudhirbharti C# 1 February 21st, 2008 01:29 PM
including unique values from a range into a combo Kaustav Excel VBA 0 November 6th, 2006 09:17 AM
Unique values from a dataset gbuller Pro VB.NET 2002/2003 3 September 27th, 2004 12:17 PM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.