Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Transform XSL into XSL 1

Status
Not open for further replies.

MikeAJ

Programmer
May 22, 2002
108
0
0
US
Hi,

I have a fairly large and complex XSL (around 1000 lines) that is used to convert XML into XHTML and display inside a webpage. I have a new situation where I need to add a header and footer to this stylesheet before I transform the XML with it. So, what I'm trying to do is write a stylesheet to transform my orginal stylesheet into a new stylesheet, and then use that for processing.

So something like this:
Code:
//Get XML and XSL
v_xml = getXML();
v_original_xsl = getXSL("largeXSL");
v_modify_xsl   = getXSL("modifyXSL");

//Transform the original stylesheet with my modify stylesheet
v_new_xsl = v_original_xsl.transform(v_modify_xsl);

//Use new stylesheet to transform my xml
v_output  = v_xml.transform(v_new_xsl);

So I'm having problems with the modify XSL working properly. Here is what I have so far:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="[URL unfurl="true"]http://www.w3.org/1999/XSL/Transform"[/URL] version="2.0" xmlns:xso="dummy">
	<xsl:output method="xml"/>
	<xsl:template match="xsl:stylesheet">
		<xso:stylesheet>
			<html>
				<body>
					<h1>Header</h1>
					<xsl:copy>
						<xsl:apply-templates/>
					</xsl:copy>
					<h1>Footer</h1>
				</body>
			</html>
		</xso:stylesheet>
	</xsl:template>
</xsl:stylesheet>

My idea was that I could add the HTML and BODY tags, as well as Header and Footer HTML to my original stylesheet. The problem is that is seems to be processing the original stylesheet instead of just copying all of its code into the new one. Is what I'm trying to do possible? Am I on the right track?

Thanks for the advice!
-Mike
 
[0] Transform xsl to a new xsl is a viable approach. However, the request functionality should be achieved clearer and much more simpler by using the import mechanism.

[1] Suppose the original xsl doc be "large.xsl". You can create the "modified.xsl" like this by importing "large.xsl".
[tt]
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="[ignore][/ignore]" version="2.0">
<xsl:import href="large.xsl" />
<xsl:template match="/">
<html>
<body>
<h1>Header</h1>
<xsl:apply-imports />
<h1>Footer</h1>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
[/tt]
[1.1] Just a detail: in the "large.xsl", I suppose you have a template rule for matching the root document "/". Otherwise, you replace that match by the top-originating match of that template.

[2] In the processing, just apply the "modify.xsl" directly to transform the data xml.
 
Hi tsuji,

I had to create a new handle because my old account is throwing an error when I log in. Anyway, thanks for the response! My XSLs are not physical files, but really just a CLOB in the database. I tried to hit my webservice to deliver the xsl by saying <xsl:import href=" />, but my xsl processor doesn't allow remote imports like that. I wish it did, it looks like a really clean way to achieve what I'm after.

So, I got a stylesheet to transform the large stylesheet almost working, but it's not quite there yet.

Here's the modify stylesheet:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="[URL unfurl="true"]http://www.w3.org/1999/XSL/Transform"[/URL] version="2.0" xmlns:xso="dummy">
	<xsl:output method="xml"/>
	<xsl:template match="xsl:stylesheet">
		<xsl:copy>
			<xsl:apply-templates select="@*|node()"/>
		</xsl:copy>
	</xsl:template>

	<xsl:template match="xsl:template[@match='/*']">
		<html>
			<body>
				<h1>Header</h1>
				<xsl:element name="{local-name()}">
					<xsl:apply-templates select="@*|node()"/>
				</xsl:element>
				<h1>Footer</h1>
			</body>
		</html>
	</xsl:template>

	<xsl:template match="*">
		<xsl:element name="{local-name()}">
			<xsl:apply-templates select="@*|node()"/>
		</xsl:element>
	</xsl:template>

	<xsl:template match="@*">
		<xsl:copy-of select="." />
	</xsl:template>

</xsl:stylesheet>

It's almost working except the resulting stylesheet leaves off the xsl: on all of my tags. So, instead of <xsl:apply-templates select="//PART" mode="javascript"/> I get <apply-templates select="//PART" mode="javascript"/>.

The other problem is where it's putting the new header and footer. Let's say the original stylesheet looks like this:
Code:
<xsl:stylesheet xmlns:xsl="[URL unfurl="true"]http://www.w3.org/1999/XSL/Transform"[/URL] version="1.0">
	<output method="html" indent="yes"/>
	<strip-space elements="*"/>
	<preserve-space elements="sp"/>
	<template match="/*">
		<script type="text/javascript">

What I need is:
Code:
<xsl:stylesheet xmlns:xsl="[URL unfurl="true"]http://www.w3.org/1999/XSL/Transform"[/URL] version="1.0">
	<output method="html" indent="yes"/>
	<strip-space elements="*"/>
	<preserve-space elements="sp"/>
	<template match="/*">
		<html>
		<body>
		<h1>Header</h1>
		<script type="text/javascript">

But, what I'm getting is:
Code:
<xsl:stylesheet xmlns:xsl="[URL unfurl="true"]http://www.w3.org/1999/XSL/Transform"[/URL] version="1.0">
	<output method="html" indent="yes"/>
	<strip-space elements="*"/>
	<preserve-space elements="sp"/>
	<html>
	<body>
	<h1>Header</h1>
	<template match="/*">
		<script type="text/javascript">

How can I get the Header code to be inside <template match="/*">?

Thanks again for the help!
-Mike
 
[3] For xsl->xsl transformation, you can do this with revision shown.
[tt]
<?xml version="1.0" encoding="UTF-8"?>
[green]<!-- no need of xso dummy device -->[/green]
<xsl:stylesheet xmlns:xsl="[ignore][/ignore]" version="2.0">
<xsl:eek:utput method="xml" [blue]encoding="UTF-8"[/blue] />
<xsl:template match="xsl:stylesheet">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>

<xsl:template match="xsl:template[@match='[highlight]/[/highlight]'">
[blue]<xsl:copy>
<xsl:attribute name="match">
<xsl:value-of select="'/'" />
</xsl:attribute>
<html>
<body>
<xsl:apply-templates select="@*|node()"/>
</body>
</html>
</xsl:copy>[/blue]
</xsl:template>

<xsl:template match="*">
[blue]<xsl:copy>[/blue]
<xsl:apply-templates select="@*|node()"/>
[blue]</xsl:copy>[/blue]
</xsl:template>

<xsl:template match="@*">
<xsl:copy-of select="." />
</xsl:template>

</xsl:stylesheet>
[/tt]
 
correction
A typo here.
[tt] <xsl:template match="xsl:template[@match='/'[red]][/red]">[/tt]
 
Hi tsuji,

Thanks so much for the help! The template is almost working perfectly. I had to remove the @ from <xsl:apply-templates select="@*|node()"/>, but otherwise it was right on the money! The last thing that seems to be happening is that it's escaping my apostrophes and quotation marks. So instead of:
<xsl:apply-templates select="//OPTION[@type='QTY']" mode="qty"/>
I'm getting:
<xsl:apply-templates select="//OPTION[@type=&apos;QTY&apos;]" mode="qty"/>

And in my javascript instead of:
var gCurrencySymbol = "
<xsl:value-of select="//PART[position()=1]/@currencySymbol"/>";

I'm getting:
var gCurrencySymbol = &quot;
<xsl:value-of select="//PART[position()=1]/@currencySymbol"/>&quot;;

I tried to disable-output-escaping in <xsl:copy-of select="."/>, but it didn't like that.

How can we get the quotes and apostrophes to come through?

Thanks again for the help!
-Mike
 
[4]>I had to remove the @ from <xsl:apply-templates select="@*|node()"/>,...[/i]
You are absolutely correct to do so. I have taken conscious on the need to remove that part but unfortunately not eventually done during the editing. But this part has a substantive detail behind concerning some kind of "bug" in the ms-implementation of the xslt.

[4.1] In the big picture, it is conceptually absolutely necessary to have that @* select removed. But msxsl won't raise error when I have the match attribute constructed as shown.

[4.2] The reason I put the xsl:attribute up there is that msxsl won't perform when @* is kept down there. (Other implementations do perform well in my limited selections.)It is kind of a bug, I would say. To workaround it is the reason I had put that part before scripting in <html><body>...

[4.3] I would prefer to put an xsl:apply-templates for the attribute nodes separately up there instead of constructing only have "match" attribute re-constructed. That originating template has every right to have more attributes scripted in. Hence, a more satisfactory form would be like this.
[tt]
<xsl:template match="xsl:template[@match='/']">
<xsl:copy>
<xsl:apply-templates select="@*" />
<html>
<body>
<xsl:apply-templates select="node()"/>
</body>
</html>
</xsl:copy>
</xsl:template>
[/tt]
That detail of construction looks odd because of the need of a work-around as mentioned above for certain ms-implementation.

[5]
>And in my javascript instead of:
>var gCurrencySymbol = "
><xsl:value-of select="//PART[position()=1]/@currencySymbol"/>";

>I'm getting:
>var gCurrencySymbol = &quot;
<xsl:value-of select="//PART[position()=1]/@currencySymbol"/>&quot;;


As far as I can see, the need of such kind of javascript section appearing in the xslt is that you output to html. But if it is outputting to xml, xhtml latently, then you can do this to the javascript section, namely construction an explicit template for matching it.
[tt]
<xsl:template match="script">
<xsl:copy-of select="." disable-output-escaping="yes" />
</xsl:template>
[/tt]
There are some inconvenience resulting in the lack of positive support of xhtml in (most?) browsers till now.

[6]
>The last thing that seems to be happening is that it's escaping my apostrophes and quotation marks. So instead of:
><xsl:apply-templates select="//OPTION[@type='QTY']" mode="qty"/>
>I'm getting:
><xsl:apply-templates select="//OPTION[@type=&apos;QTY&apos;]" mode="qty"/>

This I cannot reproduce without more twisting. Maybe it is implementation-dependent feature. But I would think it does not affect the performance of the transformed xsl document, does it?
 
Correction

[5] I edited a wrong solution. This is what I have actually in mind. In the xsl:eek:utput element, you put the cdata-section-elements attribute in there.
[tt]
xsl:eek:utput method="xml" encoding="UTF-8" indent="yes" [red]cdata-section-elements="script"[/red] />
[/tt]
[5.1] Setting disable-output-escaping in the xsl:copy-of element is actually an error, some implementation flag it and refuse to perform further, some just ignores it.
[tt]
<xsl:template match="script">
<xsl:copy-of select="." disable-output-escaping="yes" /> <!-- wrong -->
<xsl:copy-of select="." />
</xsl:template>
[/tt]
But this is no difference with the less precise match="*", hence, it is no need at all to add it. So, just forget it.
 
tsuji, thanks so much for your help and detailed explanations! It's working perfectly now! You are no doubt a guru at XSL.

Thanks again!
-Mike
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top