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 April 24th, 2007, 05:20 PM
Authorized User
 
Join Date: Apr 2007
Posts: 38
Thanks: 0
Thanked 0 Times in 0 Posts
Default node-set() -- moving from msxsl to saxon, etc.

My xslt currently uses msxsl:node-set(). This works fine when transforming xml via msxsl from the command line and also previewing it in IE7. However, msxsl:node-set() is not recognized by saxon or Firefox, so I cannot use those with my xml and xslt.

Since Vista's IE7 is having trouble w/ xslt, I'd like to preview in Firefox. While I'm at it, I would like to see if I can use Saxon instead of msxsl.

What are the recommended steps for migrating away from msxsl:node-set()?

Thanks!

Travis

 
Old April 24th, 2007, 06:20 PM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

With XSLT 2.0, the need for the node-set extension disappears entirely. So if you can wean yourself off client-side transformation, you might as well move to XSLT 2.0 and get all the other benefits as well. There are two main processors available: Saxon and Altova. Saxon of course is by far the best ;)

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
 
Old April 24th, 2007, 06:26 PM
Friend of Wrox
 
Join Date: Jul 2006
Posts: 430
Thanks: 28
Thanked 5 Times in 5 Posts
Send a message via Yahoo to bonekrusher
Default

I use both. I will have to say that SAXON out performs Altova by a a long shot. For example; I have a file that list about 870 xml file. My xslt calls each with the document function. SAXON usually runs in seconds, where Altova's takes tens of minutes...

SAXON is by far the best.

 
Old April 24th, 2007, 10:05 PM
Authorized User
 
Join Date: Apr 2007
Posts: 38
Thanks: 0
Thanked 0 Times in 0 Posts
Default

I like Saxon's error messages a lot more than msxsl's, and would prefer to use Saxon for static xhtml generation.

However, I also like to preview my xslt-powered pages in a browser before running the xslt. Up until now I've been using IE7 for all the previewing (since Firefox doesn't understand msxsl:node-set()).

Do you know if Firefox supports XSLT 2.0 enough to allow me to skip the node-set()? Or is Firefox's XSLT support still limited to XSLT 1.x? (I suspect the latter)

I'd like to baby-step towards XSLT 2.0. To do that, I would like to first try to isolate the msxsl:node-set() usage. Right now my xslt has 10 occurances of msxsl:node-set(). I'd like to put the msxsl:node-set() call in a named template, and then change all 10 references to "call" that template like a function. Does this sound like a decent plan, or am I thinking too much like a conventional programmer? I haven't done any refactoring of my xslt in years and am worried that I'm going to mess things up...

Is there a guide for isolating node-set() usage? I vaguely remember reading something about it years ago but have no idea which keywords to google.

Thanks!

 
Old April 24th, 2007, 10:22 PM
Authorized User
 
Join Date: Apr 2007
Posts: 38
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Here's an example of how I am using msxsl:node-set():
Code:
<xsl:variable name="html">
  <html>
    <head>...</head>
    <body><xsl:apply-templates select="blaa" />...</body>
  </html>
</xsl:variable>
<xsl:apply-templates mode="indent" select="msxsl:node-set($html)" />
In this instance, I'm assigning my html output (which is dynamically constructed via xslt) to a variable, which I then pass to my "indent" template (which cleans up the indentation). I use node-set() so that I can treat the html like a tree of nodes rather than a string.

I'm not sure how I can move the msxsl:node-set() reference away from this code. I can't just pass $html to some other template which calls msxsl:node-set() on it, can I?

Ideas?
 
Old April 25th, 2007, 01:59 AM
joefawcett's Avatar
Wrox Author
 
Join Date: Jun 2003
Posts: 3,074
Thanks: 1
Thanked 38 Times in 37 Posts
Default

One possibility it to embed the data in the stylesheet and use the document() function. There is also a problem with that though, not all browsers support it.
Code:
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:myData="http://joe.fawcett.name/xslt/examples"
  xmlns:msxsl="urn:schemas-microsoft-com:xslt"
  exclude-result-prefixes="msxsl myData">
  <xsl:variable name="useVariable">
    <variable/>
  </xsl:variable>
  <myData:useEmbedded>
    <embedded/>
  </myData:useEmbedded>

  <xsl:template match="/">
    <example>
      <xsl:copy-of select="msxsl:node-set($useVariable)/variable"/>
      <xsl:copy-of select="document('')/*/myData:useEmbedded/embedded"/>
    </example>  
  </xsl:template>
</xsl:stylesheet>
You can run the above with any dummy input XML.

--

Joe (Microsoft MVP - XML)
 
Old April 25th, 2007, 09:03 AM
Authorized User
 
Join Date: Apr 2007
Posts: 38
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Joe - Thanks! I tried your example (and modified it a bit). When my data contains xsl:* elements, those elements get copied to the output too. So, document('') appears to treat all contents of the selected elements literally. This would work if "embedded" contains data only, but if it contains xsl:value-of, xsl:apply-templates, etc., it doesn't work.

So, this works:
Code:
<myData:useEmbedded>
  <embedded>
    <p>hi there</p>
    <p>this is just data</p>
  </embedded>
</myData:useEmbedded>
But this doesn't (the xsl:value-of gets copied to the output):
Code:
<myData:useEmbedded>
  <embedded>
    <p>hi there</p>
    <p><xsl:value-of select="'this is xsl markup'" /></p>
  </embedded>
</myData:useEmbedded>
This sort of makes sense since document('') tries to treat xslt markup as xml data. Is this the main weakness of the document('') strategy?

NOTE: I updated my earlier example (changes in red) to emphasize that my "html" element is dynamically constructed via xslt (instead of consisting of data only).
 
Old April 25th, 2007, 09:20 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

Yes, document('') only works for fixed XML fragments.

If you want to construct an XML tree and then process it as XML in the same stylesheet, then you're basically hosed: you either need the node-set() extension, or an XSLT 2.0 processor, or a processor that implements XSLT 1.0 but lifts this restriction in the spec (I think there are one or two but don't recall the detail).

You do sometimes find the node-set() extension used where it isn't needed, inserted by people who haven't fully understood what it's for. In that case you can just replace xx:node-set($x) by $x.

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
 
Old April 25th, 2007, 09:40 AM
Authorized User
 
Join Date: Apr 2007
Posts: 38
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Thanks, Michael!

It looks like Firefox doesn't support XSLT 2.0 or a node-set() function yet. The next version of Firefox (3.0) is supposed to support exsl:node-set(), which is better than nothing, but that's probably a couple months away.

If Firefox 3.0 supports esxl:node-set() and IE7 supports msxsl:node-set() and Saxon supports XSLT 2.0, then it would be nice to isolate those differences in a single file or template. I'd love to have a single chunk of xslt detect which engine is running and then select the appropriate node-set logic. However, I realize that's a "conventional" programming tactic which might not work with xslt.

Out of curiosity, how do you preview your XSLT output? Do you use IE7 or Firefox or some other XSLT rendering tool? Or do you always use Saxon to generate static output, and then open the static output in a browser?


 
Old April 25th, 2007, 10:08 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

XSLT allows you to write code like this:

<xsl:when test="system-property('xsl:vendor')='Microsoft')">
  <xsl:value-of select="msxml:node-set($x)"/>
</xsl:when>
<xsl:when test="system-property('xsl:vendor')='Mozilla')">
  <xsl:value-of select="moz:node-set($x)"/>
</xsl:when>

etc. (You'll have to check the actual vendor names)

I usually do XSLT development work either (a) using Saxon and UltraEdit and the command line, or (b) using Saxon within Stylus Studio. If it has to run in the browser I only test in the browser once it's working elsewhere. That's because the browser environment is pretty bad for diagnostics.

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference





Similar Threads
Thread Thread Starter Forum Replies Last Post
XPath: set operation with a disjoint node set rich_unger XSLT 7 May 6th, 2008 09:24 AM
Expression must evaluate to a node-set. XMLUser XSLT 3 February 5th, 2008 01:27 PM
Converting String into Node-set dved XSLT 3 January 23rd, 2008 12:40 PM
Filtering out from a node set anothervbaddict XSLT 1 May 22nd, 2007 08:42 AM
node-set function Bernardo Pacheco XSLT 2 June 19th, 2006 10:45 AM





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