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

October 6th, 2008, 03:54 PM
|
|
Registered User
|
|
Join Date: Sep 2008
Posts: 9
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
How to deal with complex conditions in XSL file?
Hello,
I'm trying to generate something similar to the following, but with the possibility that some XML data will be blank:
University of Education, Miami, Florida (Business and Economics), PhD 1995
Here's an example of the data coming in:
<UNIVERSITY>University of Education</UNIVERSITY>
<LOCATION>Miami, Florida</LOCATION>
<MAJOR>Business and Economics</MAJOR>
<DEGREE>PhD</DEGREE>
<YEAR>1995</YEAR>
However, if blank data is coming in for the location and major, for example, I'd end up with something like the following if I don't carefully plan for all formatting conditions:
University of Education, (), PhD 1995
In other programming languages, I'd typically use variables to help clean this up. What is my best option when using XSLT? I'm thinking this could get ugly with a zillion "xsl:if" conditions if I'm not careful. Is there a best practice?
Any advise would really be appreciated. Thanks!
- Matt
|
|

October 6th, 2008, 04:03 PM
|
|
Registered User
|
|
Join Date: Sep 2008
Posts: 9
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Here's another example...
What if I have a list of five items:
<ITEM1>A</ITEM1>
<ITEM2>B</ITEM2>
<ITEM3>C</ITEM3>
<ITEM4>D</ITEM4>
<ITEM5>E</ITEM5>
Using XSLT, I can display these in a list format as follows:
A, B, C, D, E
But what if <ITEM4> and <ITEM5> are blank? I'd then be stuck with the following:
A, B, C,
If I simply incremented a string, I could check if it's been populated with a value yet, and if it has, prepend with a ", ". But from what I've found, this string method cannot be done with XSLT. That's what brings me to this post and if an alternative best practice exists for XSLT. :-)
|
|

October 6th, 2008, 04:41 PM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
Use template rules.
<xsl:template match="LOCATION">
<xsl:text>(</xsl:text>
<xsl:value-of select="."/>
<xsl:text>)</xsl:text>
</xsl:template>
<xsl:template match="LOCATION[.='']"/>
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer's Reference
|
|

October 6th, 2008, 04:47 PM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
You'd probably be better off it the design of the XML were changed so that "blank" elements were omitted completely. But if you can't do that, another approach is to omit them when you do the apply-templates:
<xsl:apply-templates select="*[.!='']"/>
Then you don't have to write special template rules for the empty elements. With your ITEMn example the rule can then be
<xsl:template match="ITEM1|ITEM2|ITEM3|ITEM4|ITEM5">
<xsl:value-of select="."/>
<xsl:if test="position()!=last()">, </xsl:if>
</xsl:template>
This works because last() here means "the last thing selected by the xsl:apply-templates instruction".
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer's Reference
|
|

October 6th, 2008, 05:22 PM
|
|
Registered User
|
|
Join Date: Sep 2008
Posts: 9
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Thanks. I tried your second "apply-templates" solution, but found it doesn't enable me to display things out of order. The following appears to grab ITEM 1, ITEM 2, ITEM 3, ITEM 4, ITEM 5, ITEM 6, and ITEM 7 instead of just five in varied order:
<xsl:template match="ITEM3|ITEM5|ITEM2|ITEM4|ITEM1">
<xsl:value-of select="."/>
<xsl:if test="position()!=last()">, </xsl:if>
</xsl:template>
Is there a way I can just grab five items starting at ITEM3 and ending at ITEM1? It would also be great if I could do additional format processing if the match happens to be ITEM2, for example.
|
|

October 6th, 2008, 05:42 PM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
In XSLT 2.0 you can do
<xsl:apply-templates select="ITEM3, ITEM7, ITEM4, ITEM6"/>
to process them in a particular order.
And of course you can write a different template rule for each kind of item.
In 1.0 you can do
<xsl:apply-templates select="ITEM3"/>
<xsl:apply-templates select="ITEM7"/>
<xsl:apply-templates select="ITEM4"/>
<xsl:apply-templates select="ITEM6"/>
but this doesn't give you the ability to use last() in the called template to detect when you are processing the last one.
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer's Reference
|
|

October 9th, 2008, 10:05 AM
|
|
Registered User
|
|
Join Date: Sep 2008
Posts: 9
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Thanks for your help, Mike. While it wasn't what I was looking for, it did help me find the solution after some experimentation. Here's my final code:
<xsl:for-each select="DATA">
<p>
<xsl:for-each select="ITEM3|ITEM5|ITEM2|ITEM4|ITEM1">
<xsl:value-of select="."/>
<xsl:if test="position() != last() and string(.)">, </xsl:if>
</xsl:for-each>
</p>
</xsl:for-each>
|
|

October 9th, 2008, 10:27 AM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
I'm glad you think your code works but it looks pretty buggy to me.
select="ITEM3|ITEM5|ITEM2|ITEM4|ITEM1"
looks as if it is trying to process the items in a very specific order, but actually it will process them in document order.
position() != last() and string(.)
looks as if it is trying to output a comma after every non-empty string except the last, but if your first three strings are non-empty and the last two are empty, then it will output a comma after the last of the three non-empty strings.
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer's Reference
|
|

October 9th, 2008, 10:35 AM
|
|
Registered User
|
|
Join Date: Sep 2008
Posts: 9
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
I just checked and you're right, Mike. Thanks for the note. Unfortunately, it doesn't look like there's a way to accomplish what I'm trying to do with XSLT.
|
|

October 9th, 2008, 11:05 AM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
>Unfortunately, it doesn't look like there's a way to accomplish what I'm trying to do with XSLT.
Rubbish. If you're using XSLT 1.0 it will probably be verbose, but it can certainly be done. Like most things, it's easier in 2.0.
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer's Reference
|
|
 |