 |
| 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
|
|
|
|

June 6th, 2006, 09:20 AM
|
|
Authorized User
|
|
Join Date: Jun 2006
Posts: 10
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Please Help!!!
Hi, I am a newbie to xsl. I have been reading a lot about xsl, I was able to transform simple xml's, but I am having a lot of trouble transforming this xml as I want it to be.
Here is the xml that I have:
<sm>
....
<Allocations>
<Item Parent="C" Level="1" class_code="C" class="Cash (C)" Allocation="0.5" />
<Item Parent="C" Level="2" class_code="00CC" class="Cash (00CC)" Allocation="0.5" />
<Item Parent="C" Level="3" class_code="CC00" class="Cash (CC00)" Allocation="0.5" />
<Item Parent="CE" Level="1" class_code="CE" class="Equity (CE)" Allocation="0.5" />
<Item Parent="CE" Level="2" class_code="00CE" class="Equity (00CE)" Allocation="0.5" />
<Item Parent="CE" Level="3" class_code="CE00" class="Equity (CE00)" Allocation="0.5" />
</Allocations>
</sm>
The above xml holds a tree's top node to bottom node. The xml above has an attribute called "Parent". According to the number of level's in the tree, I will have number of row's of Item for a particular Parent. So above, I have three level's and I have two Parents("C", CE"). For each parents, I have three items. Here is an example of what the xsl should do to the xml:
Level 1 Level 2 Level 3 Allocation Remove
Cash (C) Cash (0011) Cash (0011) 50% Delete
Equity (CE) Equity (0015) Equity (1500) 50% Delete
The first row will be the headings. And the Level headings are dynamic, so the level's could be 4, 5 and etc. So from the xml. I need to select all unique item's by Parent. And then find the MAX level of all parents. So one parent could have Level up to 3 and another parent could have level up to 5. So in this case I should return the Max level 5 and have headings (Level 1, Level 2, Level 3, Level4, Level5, Allocation, Remove). And then select the item's accordingly to display it on the screen.
The idea that I had of going about doing this is to first create the column heading since the Level's will be dynamic. So the first thing I could do is first sort everything by @Level and then get the first element's @Parent and @Level which will give me the highest level possible and a Parent which holds the highest Level. Then I could select all the Items that have Parent = @Parent. Using this I could create the headings (Level1, Level2, Level3). Then create the other two headings(Allocation, Remove). So now, I have all the headings that I need that is (Level1, Level2, Level3, Allocation, Remove).
After creating the Heading, I could create the line by doing a select distinct or something like that to get a string something like (<as>C</as><as>CE</as>). Then for each item, I could select what ever I need and create one row and display that. I have this idea, but I have no idea how to implement this since I am just learning XSL. What I have so far is this:
<xsl:template match="/">
<xsl:choose>
<xsl:when test="sm">
<xsl:apply-templates select="sm" />
</xsl:when>
<xsl:otherwise>
There are no Security Info
</xsl:otherwise>
</xsl:choose>
<xsl:call-template name="GetMax">
<xsl:with-param name="Items" select="//Allocations//Item" />
</xsl:call-template>
</xsl:template>
<xsl:template name="GetMax">
<xsl:param name="Items" />
<xsl:variable name="MaxLevel">
<xsl:for-each select="$Items">
<xsl:sort select="@Level" data-type="number" order="descending"/>
<xsl:if test="position()=1">
<xsl:copy-of select="." />
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:value-of select="MaxLevel"/>
</xsl:template>
This doesn't even get me the MaxLevel value that I need. The first call to the template works fine, but when I say call-template. It doesn't display the MaxLevel at all. Please help me. Thanks.
NewToXSL
|
|

June 6th, 2006, 09:53 AM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
I'm afraid this is quite an ambitious transformation for someone new to the language! It's also quite an ambitious question to ask on a forum like this, since there are few people prepared to devote the time needed to understand the problem in detail.
A few hints and tips:
(a) it's going to be easier if you use XSLT 2.0
(b) if you're using 1.0, you need to understand Muenchian grouping, and you'll probably need to understand recursive templates
(c) a good way of processing a "flattened hierarchy" (that is, a hierarchy where the nodes are all XML siblings, and the relationships are expressed using attribute values) is to think in terms of a recursive tree walk using xsl:apply-templates in the usual way, but following the logical tree rather than the physical XML tree.
(d) Just a little thing: you probably meant to write
<xsl:value-of select="$MaxLevel"/>
(note the "$").
Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
|
|

June 6th, 2006, 12:25 PM
|
|
Authorized User
|
|
Join Date: Jun 2006
Posts: 10
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Hi Michael Kay,
Thank you for your reply, I really appreciate it. I am going to be using xsl 1.0 not 2.0. Also, I am gonna read up on the stuff that you have told me. And also, I changed the xsl, so I call the GetMax Template from the template that I called from the first template. This works fine. I actually get the number 3 displayed. But you mentioned that I should put "$MaxLevel". This gives me an error. Also, what I was trying to get off this not just the Level, I need to get the @Parent and @Level. I am not sure how I can do this. If you could help me with that, that would be great. I will come with more questions after I am done reading up on the stuff that you have suggested. Thank you very much for your help. Thanks.
NewToXSL
|
|

June 7th, 2006, 02:45 PM
|
|
Authorized User
|
|
Join Date: Jun 2006
Posts: 10
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Hello Michael,
I got to the point, where I was able to get the column heading. But I am having trouble creating the rows.
This is what I have so far:
<xsl:template match="/">
<xsl:choose>
<xsl:when test="sm/Allocations">
<xsl:apply-templates select="sm/Allocations" />
</xsl:when>
<xsl:otherwise>
There are no Allocations for the Sec ID
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="Allocations">
<table border="0" cellspacing="0" cellpadding="4" width="100%">
<xsl:for-each select="Item[count(. | key('list', Parent)[1]) = 1]">
<xsl:for-each select="key('list', Parent)">
<xsl:sort select="Level" data-type="number" order="descending" />
<xsl:value-of select="asset_class" />
</xsl:for-each>
</xsl:for-each>
</table>
</xsl:template>
But I just can't get this to work. It's not going into the second for-each statement. I put a 'Testing' Message after the first for-each statement and it repeats the message six times, but it should only repeat two times. I don't know. I am really confused. Please help me. Thanks.
|
|

June 7th, 2006, 03:42 PM
|
|
Authorized User
|
|
Join Date: Jun 2006
Posts: 10
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Ok, I was able to get the rows displaying. Here is how I did it.
<xsl:template match="Allocations">
<table border="0" cellspacing="0" cellpadding="4" width="100%">
<xsl:for-each select="Item[generate-id()=generate-id(key('list', @Parent)[1])]">
<tr>
<xsl:for-each select="key('list', @Parent)">
<xsl:sort select="Level" data-type="number" order="descending" />
<td colspan="6" align="left"><xsl:value-of select="@asset_class" /></td>
</xsl:for-each>
<td colspan="6" align="left">50</td>
<td colspan="6" align="left">Delete</td>
</tr>
</xsl:for-each>
</table>
</xsl:template>
But I am having some trouble with the alignment of the columns. This is because I am displayng the column heading in a different template(where I created a table) and the actual rows of the table in another table(where I created another table). And these have the same properties, but they are not aligning up. Any suggestions on this matter? Thanks.
|
|

June 8th, 2006, 05:15 PM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
Perhaps Parent should be @Parent
Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
|
|
 |