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 June 14th, 2010, 05:39 PM
Registered User
 
Join Date: Jun 2010
Posts: 2
Thanks: 0
Thanked 0 Times in 0 Posts
Default how to use recursive apply vs call template

I'm new to XSL and v1.0 is what I am using to display content on a very stripped down version of Share Point (no SP Designer or anything that would make my task more achievable). I do not have the option of upgrading to XSL 2.0 and cannot import any XSL extensions, so hopefully someone can help me figure out how to work with this. Also, this may sound really stupid, but I have no idea what processor I'm using...I will assume that it's probably whatever is by MicroSoft, as I know there is a vb file that my boss wrote to parse the XML data to the XSL (I think I'm saying that right).

I have an XML list of several elements queried from a database. The table in my code will display most of these elements, others are used to sort, but are of no importance to the viewer of the final table displayed.

Sample of XML:

<Data>
<BlastLogs>
<item DateRangeByMonth="2010_2" ID="55" Date="2/3/2010 12:00:00 AM" Version="N/A" BlastType="ABORT" Error="compile failure" Code="" Developer="" Team=""

Action="ABORT" Impact="N"/>
<item DateRangeByMonth="2010_2" ID="54" Date="2/2/2010 12:00:00 AM" Version="9.44" BlastType="FULL" Error="" Code="" Developer="" Team="" Action="" Impact=""/>
<item DateRangeByMonth="2010_2" ID="52" Date="2/1/2010 12:00:00 AM" Version="9.43" BlastType="FULL" Error="issue with deployment2" Code="" Developer="" Team=""

Action="HOTFIX" Impact=""/>
<item DateRangeByMonth="2010_2" ID="53" Date="2/1/2010 12:00:00 AM" Version="9.43.1" BlastType="HOTFIX" Error="" Code="Tagger.vb" Developer="developer1"

Team="team8" Action="" Impact="Y"/>
.
.
.
<item DateRangeByMonth="2010_1" ID="90" Date="1/7/2010 12:00:00 AM" Version="9.26" BlastType="FULL" Error="" Code="" Developer="" Team="" Action="" Impact=""/>
<item DateRangeByMonth="2010_1" ID="91" Date="1/6/2010 12:00:00 AM" Version="9.25" BlastType="FULL" Error="" Code="" Developer="" Team="" Action="" Impact=""/>
<item DateRangeByMonth="2010_1" ID="92" Date="1/5/2010 12:00:00 AM" Version="9.24" BlastType="FULL" Error="" Code="" Developer="" Team="" Action="" Impact=""/>
<item DateRangeByMonth="2010_1" ID="93" Date="1/4/2010 12:00:00 AM" Version="9.23" BlastType="HOTFIX" Error="issue with deployment1" Code=""

Developer="developer2" Team="team9" Action="" Impact="Y"/>
<item DateRangeByMonth="2010_1" ID="94" Date="1/4/2010 12:00:00 AM" Version="9.23" BlastType="FULL" Error="" Code="" Developer="" Team="" Action="" Impact=""/>


Each line in the table displays Date/Version/BlastType/Error/Code/Developer/Team and I can successfully populate the table to display ALL entries as well as I can successfully show only data for 1 month that meets the hard coded date:
<xsl:for-each select="@DateRangeByMonth"/>
<xsl:if test="@DateRangeByMonth='2010_1'">
<!-- table rows defining how to display the data -->
</xsl:if>

Another thought process had me going down the path of separating out year and month, since there will be multiple:
<!-- variable to truncate -->
<xsl:variable name="myDateRange">
<xsl:for-each select="@DateRangeByMonth"/>
<xsl:value-of select="@DateRangeByMonth"/>
</xsl:variable>

<!-- variable to truncate datepart to just year -->
<xsl:variable name="myYear">
<xsl:for-each select="@DateRangeByMonth"/>
<xsl:value-of select="substring-before($myDateRange,'_')"/>
</xsl:variable>

<!-- variable to truncate datepart to just month -->
<xsl:variable name="myMonth">
<xsl:for-each select="@DateRangeByMonth"/>
<xsl:value-of select="substring-after($myDateRange,'_')"/>
</xsl:variable>

<!-- Selects date range -->
<xsl:for-each select="@DateRangeByMonth"/>
<xsl:if test="$myYear='2010'">
<xsl:if test="$myMonth='1'">
<!-- table rows defining how to display the data -->
</xsl:if>
</xsl:if>


I'm trying to get the hang of templates (apply-templates, call-template, ...) and how to use them. What I'd like to do (if this is even how templates work), is have my if = month1 or january or 2010_1 (at this point, i don't necessarily care what format), if = month2 or february or 2010_2, .... then match=item (i think) and call or apply a template to display the table with the data of monthX.

So, here's the second part of what i'm trying to do....which I'm coming to think is going to be the more difficult part. The original idea was to display a simple table of the months (row1 - jan/feb/mar, row2 - apr/may/jun, row3 - jul/aug/sep, row4 - oct/nov/dec) for each year and based on the link or choosing that month, that would be the parameter determining the data to display. Right now I have this as a separate xsl document, but i'm not exactly sure how that's how it will end up working.

Sample of simple Month table (partial):
<tr>
<td valign="middle" align="center" style="width: 25%">
<th><a href="#">January</a></th></td>
<td valign="middle" align="center" style="width: 25%">
<th><a href="#">February</a></th></td>
<td valign="middle" align="center" style="width: 25%">
<th><a href="#">March</a></th></td>
</tr>
.
.
.

If I keep it as two xsl docs working together, what do i include for the href? It doesn't like anything looking like "http://.../blablah.aspx?ReportType=BlastLogs&XSL=http://..." even if I use encoding for the not liked characters. Do I not href anything and do everything in one XSL making each month a parameter and tell it if i click on it that it displays only monthX data? So this is where I'm stuck figuring out what parameters and templates to create and how to use them correctly.

Can anyone offer any advice with what information I've provided? If necessary I can clarify further or provide more code. I'm open to any help I can get.

Thanks, in advance!
 
Old June 14th, 2010, 06:16 PM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

1. You can check what processor you are using by doing <xsl:comment><xsl:value-of select="system-property('xsl:vendor')"/></xsl:comment>

2. These lines look very odd: <xsl:for-each select="@DateRangeByMonth"/>. Two things are fishy: the select expression selects a singleton, so you only do one iteration; and the body of the loop is empty, which means you do nothing exactly once.

3. Removing these no-ops, you're left with a number of variable declarations that look like this: <xsl:variable name="myMonth">
<xsl:value-of select="substring-after($myDateRange,'_')"/>
</xsl:variable>. This is much better written as <xsl:variable name="myMonth" select="substring-after($myDateRange,'_')"/>. Not only is it shorter and more legible, but it's a lot more efficient: your variable is a simple string, rather than an XML result tree fragment containing a string.

4. At this point, I've afraid I'm starting to lose you. I suspect you're going down a blind alley, but I can't be sure. It would help to understand the output you want to produce. For example, I really don't understand what the <a href=""> links that you're outputting are supposed to link to.
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
 
Old June 15th, 2010, 01:57 PM
Registered User
 
Join Date: Jun 2010
Posts: 2
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Ok, simply stated, the goal is to move from a completely manual display of these logs to a dynamic way to display the logs as they are updated in the database.

Today there is Share Point (SP) page that has a table manually created with a list of months in it, segregated by year. When you click on MonthX, a table will display with rows containing the manually entered data (not from the db). Each month links to it's own separate page containing a table with data in it. If it's a new month, you have to use SP to design your table (or use the template from last month, as I started doing immediately upon entering this role) and populate it and add to it if you need more rows as the month continues...so on, so on...

I have taken on the task of making this a not so monthly manual routine and have back populated and keep up to date a database with all of this data to be displayed. So, not to introduce too much change for the user, I'm trying to memick the original way described above...click on a month --> displays that month's logs. I'm starting to wonder if it's going to be possible to do this....hence the question of will the month table "reference" another xsl document to display the data for monthX or given the month specified, do i pass a parameter some how or will is all be written in one XSL document?

I changed my variable declarations as you suggested bc, yes, that makes complete sense. You didn't lose me. Also, the output thus far works without those variables. They were created as I thought I would be using them in some sort of if statement or choose/when to display the data as hoped.

Here is the XSL that displays ALL the data queried from the DB. I have commented out the if statement that works to display the specified month, 1 of 2010. I am aware that I could also simply use DateRangeByMonth to specify 2010_1 to accomplish the same thing.
Code:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
  <xsl:output method="html"/>
  <xsl:template match="/">
	<style type="text/css">
	  .hotfix
	  {
	  background-color: #ffc0cb;
	  font-family: Verdana, Arial, Helvetica, sans-serif; 
	  font-size: 9pt;
	  }
	  .abort
	  {
	  background-color: #E80000;
	  font-family: Verdana, Arial, Helvetica, sans-serif; 
	  font-size: 9pt;
	  }
	  .header
	  {
	  font-family: Verdana, Arial, Helvetica, sans-serif; 
	  font-size: 14pt;
	  background-color: #87ceeb;
	  text-align: center;		
	  vertical-align: middle;			
	  }
	  .subheader
	  {
	  font-family: Verdana, Arial, Helvetica, sans-serif; 
	  font-size: 9pt;
	  text-align: center;		
	  vertical-align: middle;			
	  }
	  .footer
	  {
	  text-align: center !important ;
	  font-weight: bold;	
	  white-space: nowrap;	  
	  }            
	</style>

	<table border="2">
	  <tr><xsl:attribute name="class">header</xsl:attribute>
		<td colspan="8" align="center"><th> Deployment Blast Logs </th></td>
	  </tr>
	  <tr><xsl:attribute name="class">subheader</xsl:attribute>
		<td style="width: 55px;" valign="middle" align="center"><th>Date</th></td>
		<td style="width: 55px;" valign="middle" align="center"><th>Version</th></td>
		<td style="width: 60px;" valign="middle" align="center"><th>Blast Type</th></td>
		<td style="width: 400px;" valign="middle" align="center"><th>Error</th></td>
		<td style="width: 300px;" valign="middle" align="center"><th>Code Responsible</th></td>
		<td style="width: 75px;" valign="middle" align="center"><th>Developer Responsible</th></td>
		<td style="width: 75px;" valign="middle" align="center"><th>Team Responsible</th></td>
		<td style="width: 60px;" valign="middle" align="center"><th>Action</th></td>
	  </tr>
	  <xsl:apply-templates select="//item" />
	</table>
  </xsl:template>

  <xsl:template match="item">
	
	<!-- variable to truncate full datetime to just date --> 
	<xsl:variable name="myDate" select="@Date" />
		
	<!-- variable to truncate -->
	<xsl:variable name="myDateRange" select="@DateRangeByMonth"/>

	<!-- variable to truncate datepart to just year -->
	<xsl:variable name="myYear" select="substring-before($myDateRange,'_')"/>

	<!-- variable to truncate datepart to just month -->	
	<xsl:variable name="myMonth" select="substring-after($myDateRange,'_')"/>

	
	<!-- Selects date range --> 
<!-- 	<xsl:for-each select="@DateRangeByMonth"/>
	<xsl:if test="$myYear='2010'">
	  <xsl:if test="$myMonth='1'"> -->
	  <tr>
		<!-- Highlights for Hotfixes and Aborts -->
		<xsl:attribute name="class">subheader</xsl:attribute> 
		  <xsl:for-each select="@BlastType" /> 
		  <xsl:if test="@BlastType='HOTFIX'">
			<xsl:if test="@Impact='Y'">
			  <xsl:attribute name="class">hotfix</xsl:attribute> 
			</xsl:if>
		  </xsl:if>
		<xsl:if test="@BlastType='ABORT'">
		  <xsl:attribute name="class">abort</xsl:attribute> 
		</xsl:if>

		<!-- Populating columns for each item row in the table --> 
		<xsl:element name="td">
		  <xsl:attribute name="class">ms-vb</xsl:attribute> 
		  <xsl:attribute name="align">center</xsl:attribute> 
			<!-- truncate myDate to just m/d/yyyy-->
			<xsl:value-of select="substring-before($myDate,' 12:00:00 AM')" /> 
		</xsl:element>
		<xsl:element name="td">
		  <xsl:attribute name="class">ms-vb</xsl:attribute> 
		  <xsl:attribute name="align">center</xsl:attribute> 
			<xsl:value-of select="@Version" /> 
		</xsl:element>
		<xsl:element name="td">
		  <xsl:attribute name="class">ms-vb</xsl:attribute> 
		  <xsl:attribute name="align">center</xsl:attribute> 
			<xsl:value-of select="@BlastType" /> 
		</xsl:element>
		<xsl:element name="td">
		  <xsl:attribute name="class">ms-vb</xsl:attribute> 
		  <xsl:attribute name="align">left</xsl:attribute> 
			<xsl:value-of select="@Error" /> 
		</xsl:element>
		<xsl:element name="td">
		  <xsl:attribute name="class">ms-vb</xsl:attribute> 
		  <xsl:attribute name="align">left</xsl:attribute> 
			<xsl:value-of select="@Code" /> 
		</xsl:element>
		<xsl:element name="td">
		  <xsl:attribute name="class">ms-vb</xsl:attribute> 
		  <xsl:attribute name="align">left</xsl:attribute> 
			<xsl:value-of select="@Developer" /> 
		</xsl:element>
		<xsl:element name="td">
		  <xsl:attribute name="class">ms-vb</xsl:attribute> 
		  <xsl:attribute name="align">left</xsl:attribute> 
			<xsl:value-of select="@Team" /> 
		</xsl:element>
		<xsl:element name="td">
		  <xsl:attribute name="class">ms-vb</xsl:attribute> 
		  <xsl:attribute name="align">center</xsl:attribute> 
			<xsl:value-of select="@Action" /> 
		</xsl:element>
	  </tr>
<!-- 	  </xsl:if>
	</xsl:if> -->
	</xsl:template>
</xsl:stylesheet>
What I think needs to happen is that this last template that actually displays a row for each line of data, needs to be one that can be called (or applied...this is what i'm confused about) for each month. And then somehow (either in this xsl or a separate), I build the month table to display use this as well.

Does that give a better idea of what I'm trying to accomplish? Thanks again!





Similar Threads
Thread Thread Starter Forum Replies Last Post
Exit from recursive apply-templates scubin XSLT 4 May 1st, 2010 07:46 PM
Difference between call-template ,apply-templates vikkiefd XSLT 4 March 12th, 2008 05:09 AM
Recursive Template Help bucky483 XSLT 1 July 20th, 2007 12:21 PM
Recursive template - Please Help! Tre XSLT 5 March 20th, 2007 11:23 AM
Using a recursive template for various nodes spencer.clark XSLT 5 August 2nd, 2005 03:49 PM





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