[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message] Excluding too much in 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>
<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
|
PURCHASE STYLUS STUDIO ONLINE TODAY!Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced! Download The World's Best XML IDE!Accelerate XML development with our award-winning XML IDE - Download a free trial today! Subscribe in XML format
|