|
We use XSLT to convert various XML files into tab delimited.
Some of the XML input files have a variable number of options. Sometimes none, others 1,2,3 or more.
This makes the formatting difficult since there is also a header row that is created in the XSLT file that must have the exact number of columns and proper header context.
So the question is how to get this formatted correctly since if we provide for 2 sets of opts (from the W3Schools tryit) in the header row how to get the for-each to stop at 2.
<cd>
<title>Eros</title>
<artist>Eros Ramazzotti</artist>
<country>EU</country>
<company>BMG</company>
<price>9.90</price>
<year>1997</year>
</cd>
<cd>
<opts length="3">
<opt><name>Nm1</name><val>111</val></opt>
<opt><name>Nm2</name><val>222</val></opt>
<opt><name>Nm3</name><val>333</val></opt>
</opts>
Typical for-each
<xsl:for-each select="opts/opt">
<td><xsl:value-of select="name"/></td>
<td><xsl:value-of select="val"/></td>
</xsl:for-each>
In this case there will be 3 sets of opts but 2 sets of headers and all data after this will be off.
Tried using xls:when test="@length =...' but don't see a way of just getting 2 of the 3 opts.
Can anyone help?
Thanks
|
|
|
|
|
|
Thanks
Yes, using the Position() function did help but part 2 of this was still a lot more code that had to be added to complete what I needed to and I do not like it.
<b>How do we code for the mininum number of iternations when the input XML has less than the minimum?</b>
The Position did limit the output to the number of iterations we needed to see but it did nothing to fill in if the number of iterations was LESS that what we expected.
In our case the input XML had a length attribute.
<pre lang="xml">
<Opt length="1"><Opts>data</Opts></Opt></pre>
So we had to add a bunch of if or choose statements
<xls:if test="@length = "1">
...fill put in 4 output empty values
</xls:if>
<xls:if test="@length = "2">
...fill put in 3 output empty values
</xls:if>
Is there a better way?
-- modified 17-Dec-12 6:52am.
|
|
|
|
|
Hi,
I haven't done anything like this before but I did a quick bit of hunting around and something like this might do it for you. Please note this is totally untested and is just an idea. I thought about how to do a while or a normal for loop in XSL and then try and find away of checking if the <opt> element at position x existed. This is cobbled together from a couple of SO posts and my own take on how to put it together.
Sources:
http://stackoverflow.com/questions/11127693/how-to-do-a-while-like-loop-in-xslt[^]
http://stackoverflow.com/questions/5791053/xslt-if-tag-exists-apply-template-if-not-choose-static-value[^]
http://www.sourceware.org/ml/xsl-list/2000-08/msg01503.html[^]
From those articles this is what I have cobbled together:
<xsl:template name="for_loop">
<xsl:param name="num">1</xsl:param>
<xsl:param name="limit"></xsl:param>
<xsl:if test="not($num = $limit)">
<xsl:choose>
<xsl:when test="not(opt[position() = $num)">
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
<xsl:call-template name="for_loop">
<xsl:with-param name="num">
<xsl:value-of select="$num + 1">
</xsl:with-param>
<xsl:with-param name="limit">
<xsl:value-of select="$limit">
</xsl:with-param>
</xsl:call-template>
</xsl:if>
</xsl:template>
Hope this helps.
Chris
|
|
|
|
|
Yes, I started to look at params and variables but with the complexity of the multiple templates I just could not get it to work. The XSLT is too big as it is and it was hard to put it all together.
I will have to re-look at it and perhaps test with a small XSLT until I can get the multi-templates and for loop template to work.
Thanks!
|
|
|
|
|
Hi,
not sure if this is any help, I have used this to produce a student timetable grid. It does not do anything fancy at all, but it does use params and nested templates. It's quite old now and i'm sure it could be improved no end but it works well and might be of interest.
Chris
="1.0"="UTF-8"
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="/">
<xsl:if test="pupil/details[count(.) != 0]">
<h1>Week A</h1>
<table class="ec-gridview" width="100%">
<xsl:apply-templates select="pupil/details [@weekCode='A'][1]" mode="weekheader"/>
<xsl:apply-templates select="pupil/details [@weekCode='A'][1]" mode="weekdata">
<xsl:with-param name="week">A</xsl:with-param>
</xsl:apply-templates>
</table>
<xsl:apply-templates select="pupil/details [@weekCode='A'][1]" mode="ott">
<xsl:with-param name="week">A</xsl:with-param>
</xsl:apply-templates>
<br/>
<h1>Week B</h1>
<table class="ec-gridview" width="100%">
<xsl:apply-templates select="pupil/details [@weekCode='B'][1]" mode="weekheader"/>
<xsl:apply-templates select="pupil/details [@weekCode='B'][1]" mode="weekdata">
<xsl:with-param name="week">B</xsl:with-param>
</xsl:apply-templates>
</table>
<xsl:apply-templates select="pupil/details [@weekCode='B'][1]" mode="ott">
<xsl:with-param name="week">B</xsl:with-param>
</xsl:apply-templates>
</xsl:if>
</xsl:template>
<xsl:template match="details" mode="weekheader">
<tr class="ec-gridrow-header">
<th class="ec-gridheader" scope="col" style="width:5%;text-align:center"></th>
<th class="ec-gridheader" scope="col" style="width:16%;text-align:center">Mon</th>
<th class="ec-gridheader" scope="col" style="width:16%;text-align:center">Tue</th>
<th class="ec-gridheader" scope="col" style="width:16%;text-align:center">Wed</th>
<th class="ec-gridheader" scope="col" style="width:16%;text-align:center">Thu</th>
<th class="ec-gridheader" scope="col" style="width:16%;text-align:center">Fri</th>
<th class="ec-gridheader" scope="col" style="width:16%;text-align:center">Sat</th>
</tr>
</xsl:template>
<xsl:template match="details" mode="weekdata">
<xsl:param name="week"/>
<tr class="ec-odd-line">
<td class="ms-vb" style="vertical-align:text-top;text-align:center">
1
</td>
<xsl:apply-templates select="//details[@lessonNumber='1' and @weekCode=$week]" mode="p1-6"/>
</tr>
<tr class="ec-even-line">
<td class="ms-vb" style="vertical-align:text-top;text-align:center">
2
</td>
<xsl:apply-templates select="//details[@lessonNumber='2' and @weekCode=$week]" mode="p1-6"/>
</tr>
</xsl:template>
<xsl:template match="details" mode="ott">
<xsl:param name="week"/>
<xsl:if test="count(//details [@lessonNumber > 299 and @weekCode=$week]) != 0">
<h1 class="ms-rteCustom-ArticleHeadLine">Lessons not on the timetable</h1>
<xsl:for-each select="//details [@lessonNumber > 299 and @weekCode=$week]">
<a>
<xsl:attribute name="href">
../Information/Set/SetLists.aspx?IsetCode=<xsl:value-of select="@setCode"/>
</xsl:attribute>
<xsl:value-of select="@setCode"/>
</a> (<xsl:value-of select="@subjectName"/>) <xsl:value-of select="@description"/><br/>
</xsl:for-each>
</xsl:if>
</xsl:template>
<xsl:template match="details" mode="p1-6">
<xsl:for-each select=".">
<td style="vertical-align:text-top;text-align:center;min-height:60px;">
<xsl:attribute name="class">
<xsl:choose>
<xsl:when test="@currentLesson = 'Y'">ms-vb-cp</xsl:when>
<xsl:when test="@setCode = 'BLANK'">
<xsl:choose>
<xsl:when test ="@dayIndex = '1' and @lessonNumber = '6'">ms-vb-empty</xsl:when>
<xsl:when test ="@dayIndex = '2' and (@lessonNumber = '5' or @lessonNumber = '6')">ms-vb-empty</xsl:when>
<xsl:when test ="@dayIndex = '3' and @lessonNumber = '6'">ms-vb-empty</xsl:when>
<xsl:when test ="@dayIndex = '4' and (@lessonNumber = '5' or @lessonNumber = '6')">ms-vb-empty</xsl:when>
<xsl:when test ="@dayIndex = '5' and @lessonNumber = '6'">ms-vb-empty</xsl:when>
<xsl:when test ="@dayIndex = '6' and (@lessonNumber = '5' or @lessonNumber = '6')">ms-vb-empty</xsl:when>
<xsl:when test ="@dayIndex = '8' and @lessonNumber = '6'">ms-vb-empty</xsl:when>
<xsl:when test ="@dayIndex = '9' and (@lessonNumber = '5' or @lessonNumber = '6')">ms-vb-empty</xsl:when>
<xsl:when test ="@dayIndex = '10' and @lessonNumber = '6'">ms-vb-empty</xsl:when>
<xsl:when test ="@dayIndex = '11' and (@lessonNumber = '5' or @lessonNumber = '6')">ms-vb-empty</xsl:when>
<xsl:when test ="@dayIndex = '12' and @lessonNumber = '6'">ms-vb-empty</xsl:when>
<xsl:when test ="@dayIndex = '13' and (@lessonNumber = '5' or @lessonNumber = '6')">ms-vb-empty</xsl:when>
<xsl:otherwise>ms-vb</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>ms-vb</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<xsl:choose>
<xsl:when test="@setCode != 'BLANK'">
<xsl:value-of select="@subjectName"/>
<br/>
<a>
<xsl:attribute name="href">
../Information/Set/SetLists.aspx?IsetCode=<xsl:value-of select="@setCode"/>
</xsl:attribute>
<xsl:value-of select="@setCode"/>
</a>
<br/>
<a>
<xsl:attribute name="href">
../Information/Room/RoomDetails.aspx?IroomCode=<xsl:value-of select="@room"/>
</xsl:attribute>
Room <xsl:value-of select="@room"/>
</a>
<br/>
<xsl:for-each select="teacher">
<xsl:value-of select="@teacher"/>
<br/>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:text xml:space="preserve"> </xsl:text>
<br/>
<xsl:text xml:space="preserve"> </xsl:text>
<br/>
<xsl:text xml:space="preserve"> </xsl:text>
<br/>
<xsl:text xml:space="preserve"> </xsl:text>
<br/>
</xsl:otherwise>
</xsl:choose>
</td>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
|
|
|
|