RE: deep "copy-of" a source fragment
Hi Terence! Welcome to the list! This was a highly tricky one, and since you didn't give us a sample of your XML it took me a while to figure it out... The problem is not what you think it is, though :) Before giving you the answer, the first thing that puzzled me was how it could copy just text nodes... With <xsl:value-of> this is extremely easy, but not so with <xsl:copy-of> (for sake of trivia, <xsl:copy-of select="text()"/> should do the trick). The other question was how changing your XPath expression didn't change anything... Peter (below) hit the first issue perfectly. The problem is that your xsl:copy-of ---WASN'T DOING ANYTHING---! Changing the match expression was causing the default template rule for text to run which was copying your text nodes. This was giving the illusion of your statement copying just the text. The bigger question is WHY wasn't the copy-of doing anything. This was actually trickier, and I haven't seen the answer posted yet. If you take a look at HTML Tidy's XHTML output, you should see the following line: <html xmlns="http://www.w3.org/1999/xhtml"> The key here (as dozens of people will tell you) is that a namespace is in use, even though it is the default. This causes every XPath expression without a prefix to fail (this is a FAQ). To solve this, simply change your XSLT to: <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:x="http://www.w3.org/1999/xhtml"> <xsl:template match="x:body"> <xsl:copy-of select="node()"/> <!-- copies the children exclusive of body --> </xsl:template> <!-- change the default text rule to not output text --> <xsl:template match="text()"/> </xsl:stylesheet> Thanks for the puzzler, and HTH! Dion -----Original Message----- From: Peter Davis [mailto:pdavis152@xxxxxxxxx] Sent: Wednesday, September 04, 2002 12:06 AM To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx Subject: Re: deep "copy-of" a source fragment On Tuesday 03 September 2002 23:48, Terence Kearns wrote: > but if I change > match="/" > to > match="/html/body" > > then I get leaf nodes again :( > I also tried ... > makes no difference if I change > > select="node()" > to > select="." > or > select="@*|node()" > > Is there no way at all to copy a fragment from the source tree onto the > result tree?! The problem is, if you have: <xsl:template match="/html/body"> ... </xsl:template> then the default template will be applied to all the nodes that aren't part of /html/body. The default template is to copy text nodes and ignore everything else, so that might explain your problem. Instead of changing select to select="node()" and match="/html/body", you should try, <xsl:template match="/"> <xsl:copy-of select="html/body/node()"/> </xsl:template> If that doesn't work, then I don't know what's wrong. An alternative to using copy-of is to use the "identity template", which can look something like this (untested): <!-- ignore all nodes unless otherwise specified --> <xsl:template match="node()" priority="0"/> <xsl:template match="/html/body//@* | /html/body//node()"> <xsl:copy> <xsl:apply-templates select="@*"/> <xsl:apply-templates select="node()"/> </xsl:copy> </xsl:template> You might want to go this route if you ever want to apply other templates to specific elements in the /html/body//* tree. Using xsl:copy-of doesn't allow you to modify the output of the copy with other templates. If you don't think you'll ever need to apply other templates, then copy-of should work fine. -- Peter Davis XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
PURCHASE STYLUS STUDIO ONLINE TODAY!
Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!
Download The World's Best XML IDE!
Accelerate XML development with our award-winning XML IDE - Download a free trial today!
Subscribe in XML format