Wrox Programmer Forums

Need to download code?

View our list of code downloads.

Go Back   Wrox Programmer Forums > XML > XSLT
Password Reminder
Register
| FAQ | Members List | Search | Today's Posts | Mark Forums Read
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 tens of thousands of software programmers and website developers including Wrox book authors and readers. As a guest, you can read any forum posting. By joining today you can post your own programming questions, respond to other developers’ questions, and eliminate the ads that are displayed to guests. Registration is fast, simple and absolutely free .
DRM-free e-books 300x50
Reply
 
Thread Tools Search this Thread Display Modes
  #1 (permalink)  
Old March 10th, 2008, 11:19 PM
Authorized User
 
Join Date: Mar 2008
Location: , , .
Posts: 29
Thanks: 0
Thanked 0 Times in 0 Posts
Default Usage of '*' in test condition of <xsl:when>

Hi,

Could any body explain about the significance of "*" when we using in <xsl:when> as one of the test condition. The code is looking as follows:

<xsl:template match="/">
<xsl:variable name="nodeFirstTwo">
  <xsl:value-of select="substring(name(*),2,2)" /> </xsl:variable>
<xsl:choose>
 <xsl:when test="*[$nodeFirstTwo='74']>
  <xsl:apply-templates select="*[substring(name(),2,2)='74']"/>
 </xsl:when>
</xsl:choose>
</xsl:template>

<xsl:template match="*[substring(name(),2,2)='74']">
 <Error>
  <xsl:value-of select="substring(name(),'_')/>
 </Error>
</xsl:template>

Also could you explain how the test condition is getting evaluated here. Also what will be the nodeset from <xsl:apply-templates> ?
Thanks in advance for your help.

Reply With Quote
  #2 (permalink)  
Old March 11th, 2008, 03:50 AM
mhkay's Avatar
Wrox Author
Points: 18,487, Level: 59
Points: 18,487, Level: 59 Points: 18,487, Level: 59 Points: 18,487, Level: 59
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Apr 2004
Location: Reading, Berks, United Kingdom.
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

The XPath expression * selects all the element children of the context node. With a predicate, *[CONDITION] it selects all the element children where the CONDITION is true. If you use an expression like this in a boolean context (the test attribute of xsl:when) then the result is true if one or more nodes are selected, false if nothing is selected.

So:

test="*[substring(name(),2,2)='74']"

succeeds if there is at least one element child whose name has "74" in positions 2 and 3.

The expression:

*[$nodeFirstTwo='74']

is a bit peculiar because the condition $nodeFirstTwo='74' does not depend in any way on the node that you are applying it to - it will either be true for all children, or false for all of them. So this xsl:when succeeds provided that (a) there is at least one element child, and (b) the value of $nodeFirstTwo is equal to "74".

Now let's look at the variable declaration:

<xsl:variable name="nodeFirstTwo">
  <xsl:value-of select="substring(name(*),2,2)" /> </xsl:variable>

Firstly, this is a very convoluted way of writing:

<xsl:variable name="nodeFirstTwo" select="substring(name(*),2,2)" />

What you want is a string, but instead of defining the variable as a string you are evaluating the string, putting the result into a text node, attaching that text node to a document node, and then computing the string value of the document node every time you reference the variable. If you don't care about performance and if you are bonused on the number of lines of code you write, this is fine, but otherwise it's horrible. Can't blame you though, it's an incredibly common blunder.

Next point. name(*). The name() function applies to a single node. In XSLT 1.0, if you give it a sequence containing several nodes, it will select the first one. In XSLT 2.0, this is an error. However, you're within match="/", so there will only be one element node, so this is OK. However, the net result is that

test="*[$nodeFirstTwo='74']"

is just a longwinded way of saying

test="$nodeFirstTwo='74'"

Now, the apply-templates

<xsl:when test="*[$nodeFirstTwo='74']>
  <xsl:apply-templates select="*[substring(name(),2,2)='74']"/>
 </xsl:when>

You've established in the xsl:when that the document element will have a name that matches [substring(name(),2,2)='74']. So giving the condition again in the apply-templates is completely redundant.

And then you test it a third time!

<xsl:template match="*[substring(name(),2,2)='74']">


Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
Reply With Quote
  #3 (permalink)  
Old March 11th, 2008, 06:38 AM
Authorized User
 
Join Date: Mar 2008
Location: , , .
Posts: 29
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Hi Michael,

Thanks a lot for your detailed explanation.

Reply With Quote
  #4 (permalink)  
Old March 11th, 2008, 08:45 AM
Authorized User
 
Join Date: Mar 2008
Location: , , .
Posts: 29
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Hi Michael,

Thanks for the response. As per the xsl that I have, in the test condition of <xsl:when> we are similarly checking for 75 and 76 also as like 74. Its also continuing in <xsl:apply-templates> and <xsl:template> part. So could you provide any suggestions to change that which in turn help me to improve its performance.

Reply With Quote
  #5 (permalink)  
Old March 12th, 2008, 06:45 PM
mhkay's Avatar
Wrox Author
Points: 18,487, Level: 59
Points: 18,487, Level: 59 Points: 18,487, Level: 59 Points: 18,487, Level: 59
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Apr 2004
Location: Reading, Berks, United Kingdom.
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

Firstly, I think it's mighty odd to be testing an XML name to see whether the 2nd and 3rd characters are "74" - it means someone has decided to pack information into the name that should be in an attribute.

But that's not really the point. It would apply equally to any other condition that you're testing. I don't really understand your last comment, except that it suggests you didn't understand mine. Basically, you should normally put a predicate either on the xsl:template or on the xsl:apply-templates, but not usually both. Which one you choose depends on the logic of the stylesheet as a whole, which I don't think you've explained.

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
Reply With Quote
  #6 (permalink)  
Old March 12th, 2008, 10:31 PM
Authorized User
 
Join Date: Mar 2008
Location: , , .
Posts: 29
Thanks: 0
Thanked 0 Times in 0 Posts
Default

I will explain the scenario: If the input xml has the elements which are having 2nd,3rd characters as 74,75 & 76 , then they are error elements. We need to be replace them with some error tags which will be present in another template .This template needs to be called if 74,75,76 are present in input xml tags.

Reply With Quote
Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
embedded <xsl:element> into <xsl:with-param> petergoodman XSLT 2 July 9th, 2008 06:36 AM
Performance for <xsl:import> and <xsl:include> vikkiefd XSLT 2 April 16th, 2008 08:06 AM
<xsl:for-each> inside another <xsl:for-each> suersh79 XSLT 2 December 29th, 2006 01:24 AM
<xsl:if test="" Question kwilliams XSLT 2 August 9th, 2005 08:30 AM
<xsl:choose> and <xsl:otherwise> problem djmarquette XSLT 4 January 21st, 2005 01:56 PM



All times are GMT -4. The time now is 11:48 AM.


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