[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Excluding too much in nested for-each

Subject: Excluding too much in nested for-each
From: "Ragulf Pickaxe" <jawxml@xxxxxxxxxxx>
Date: Wed, 21 Apr 2004 06:00:44 +0000
xsl nested for each
Hi all,

This post is a little long, but I have cut it down to the least that can also give a description of the problem (I hope).
I hope that some of you have the time to look at this, and that it is understandable.


I had a question a coupple of years ago, and have only now found a bug in the solution - problem is that I don't know how to correct it. I have tried to find the original posts in the archieves, but not been able to do so.

I have an XML that is flat, which I want to output in a tree view:

<!-- Simplified -->
<root>
<Elements>
 <Elem Date="01-01-2003" Type="1"> <!-- A -->
   <ElemID>10</ElemID>
   <Name>A</Name>
 </Elem>
 <Elem Date="01-01-2003" Type="2"> <!-- B -->
   <ElemID>10</ElemID>
   <Name>B</Name>
 </Elem>
 <Elem Date="01-01-2003" Type="2"> <!-- C -->
   <ElemID>10</ElemID>
   <Name>C</Name>
 </Elem>
 <Elem Date="01-04-2003" Type="2"> <!-- D -->
   <ElemID>10</ElemID>
   <Name>D</Name>
 </Elem>
 <Elem Date="01-04-2003" Type="2"> <!-- E -->
   <ElemID>13</ElemID>
   <Name>E</Name>
 </Elem>
 <Elem Date="01-08-2003" Type="1"> <!-- F -->
   <ElemID>12</ElemID>
   <Name>F</Name>
 </Elem>
 <Elem Date="01-08-2003" Type="2"> <!-- G -->
   <ElemID>13</ElemID>
   <Name>G</Name>
 </Elem>
 <Elem Date="01-08-2003" Type="2"> <!-- H -->
   <ElemID>13</ElemID>
   <Name>H</Name>
 </Elem>
 <Elem Date="01-08-2003" Type="2"> <!-- I -->
   <ElemID>13</ElemID>
   <Name>I</Name>
 </Elem>
 <Elem Date="01-08-2003" Type="3"> <!-- J -->
   <ElemID>14</ElemID>
   <Name>J</Name>
 </Elem>
</Elements>
</root>

The caveat is, that I do not want elements (Elem) of Type="1" in the output.
With the help of Jeni T. at the time (limited by my understanding), I got the following XSL-fragment:


<xsl:template name="group-by-date">
<xsl:variable name="unique-dates" select="/root/Elements/Elem/[not(@Date=preceding-sibling::Elem/@Date)]/@Date"/>
<output>
<xsl:for-each select="$unique-dates">
<xsl:sort select="substring(.,$YearPos,4)" order="descending"/>
<xsl:sort select="substring(.,$MonthPos,2)" order="descending"/>
<xsl:sort select="substring(.,$DayPos,2)" order="descending"/>


<OutputByDate><Date><xsl:value-of select="."/></Date>

<xsl:for-each select="/root/Elements/Elem[@Date=current()][not(preceding-sibling::Elem[@Date=current()]/ElemID=ElemID][not(@Type='1' or

@Type='3']"/> <!-- This for-each line gives the problem -->
     <OutputElem><ID><xsl:value-of select="ElemID"/></ID>

<xsl:for-each select="/root/Elements/Elem[@Date=current()/@Date][ElemID=current()/ElemID][not(@Type='1' or

@Type='3']"/>

<OutputElemSub><Type><xsl:value-of select="@Type"/></OutputElemSub>

     </xsl:for-each> <!-- End of single Elem item -->
     </OutputElem>
   </xsl:for-each> <!-- End of cluster of Elem items -->
   </OutputByDate>
 </xsl:for-each> <!-- End of Date the items are grouped by -->
 </output>
</xsl:template>


<output> <OutputByDate><Date>01-08-2003</Date> <OutputElem><ID>13</OutputElem> <OutputElemSub><Type>2</Type><Name>G</Name></OutputElemSub> <OutputElemSub><Type>2</Type><Name>H</Name></OutputElemSub> <OutputElemSub><Type>2</Type><Name>I</Name></OutputElemSub> </OutputElem> <OutputElem><ID>14</ID> <OutputElemSub><Type>2</Type><Name>J</Name></OutputElemSub> </OutputElem> </OutputByDate>

 <OutputByDate><Date>01-04-2003</Date>
   <OutputElem><ID>10</OutputElem>
     <OutputElemSub><Type>2</Type><Name>D</Name></OutputElemSub>
   </OutputElem>
   <OutputElem><ID>13</OutputElem>
     <OutputElemSub><Type>2</Type><Name>E</Name></OutputElemSub>
   </OutputElem>
 </OutputByDate>
</output>


Elements <!-- F --> is rightfully not in the output as it is of @Type='1'


The problem is that so is the case of elements <!-- B --> and <!-- C -->. I wanted the same output as above but including

the following:

 <OutputByDate><Date>01-01-2003</Date>
   <OutputElem><ID>10</OutputElem>
     <OutputElemSub><Type>2</Type><Name>B</Name></OutputElemSub>
     <OutputElemSub><Type>2</Type><Name>C</Name></OutputElemSub>
   </OutputElem>
 </OutputByDate>

Notice that the <!-- A --> element - of @Type='1' - is not in the wanted output.


A further problem is that I cannot make the XPath exclusion of elements with their only children being of @Type='1' or


@Type='3' at the same time as grouping them.

I have tried making a variable which contains all the valid elements in the top of the template:
<xsl:variable name="ValidElems" select="/root/Elements/Elem[(@Type='2' or @Type='4')]"/>


The second for-each could then loop through this:
<xsl:for-each select="$ValidElems[@Date=current()][not(preceding-sibling::Elem[@Date=current()]/ElemID=ElemID]"/>
The problem is with the second predicate which goes through the input document, not only those contained in the variable


and which therefore will give <!-- F --> in the output too.

I do not know how to change this so that it does go through only the elements contained only in the variable $ValidItems

or how to make the solution otherwise.

I have nothing against key's if that is a solution, I have just never worked with key's in XSL, and is therefore not

proficient in this, but if a solutions with key's is easier, then I will very much want to learn.

Thanks in advance,
Ragulf Pickaxe :-|

_________________________________________________________________
Tired of spam? Get advanced junk mail protection with MSN 8. http://join.msn.com/?page=features/junkmail


Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.