XSL: simple?

C

chris

Hi,

After going back through the XSL tutorials and the help here I have
largely solved the problem of merging two XHTML files, but one small
detail remains...

The parser outputs

<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:xhtml="http://www.w3.org/1999/xhtml">

I would like it to output

<html xmlns="http://www.w3.org/1999/xhtml">

or simply

<html>

How can this be done? This is the stylesheet (I think it's
syntactically correct, but I thought the last one was so...). It takes
two well formed XHTML documents (one given as input to parser and
another as a parameter) and outputs the head of the first and combines
their bodies.


<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xhtml="http://www.w3.org/1999/xhtml"
xmlns="http://www.w3.org/1999/xhtml">

<xsl:eek:utput method = "xml"
version = "1.0"
omit-xml-declaration = "no"
encoding = "UTF-8"
indent = "yes"
doctype-public = "-//W3C//DTD XHTML 1.0 Strict//EN"
doctype-system =
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"/>

<xsl:param name="leftDocument">menu.xml</xsl:param>

<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>

<xsl:template match="xhtml:html">
<html>
<xsl:copy-of select="xhtml:head"/>
<body>
<xsl:apply-templates select="xhtml:body"/>
</body>
</html>
</xsl:template>

<xsl:template match="xhtml:body">
<xsl:param name="main">yes</xsl:param>
<xsl:choose>
<xsl:when test="$main='yes'">
<xsl:apply-templates
select="document($leftDocument)/xhtml:html/xhtml:body">
<xsl:with-param name="main">no</xsl:with-param>
</xsl:apply-templates>
<div id="rightcontent">
<xsl:apply-templates />
</div>
</xsl:when>
<xsl:eek:therwise>
<div id="leftcontent">
<xsl:apply-templates />
</div>
</xsl:eek:therwise>
</xsl:choose>
</xsl:template>

<xsl:template match="node()|@*">
<xsl:copy-of select="."/>
</xsl:template>
</xsl:transform>


Thanks,
Chris
 
M

Martin Honnen

chris said:
Hi,

After going back through the XSL tutorials and the help here I have
largely solved the problem of merging two XHTML files, but one small
detail remains...

The parser outputs

<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:xhtml="http://www.w3.org/1999/xhtml"

I would like it to output

<html xmlns="http://www.w3.org/1999/xhtml">

You can use
<xsl:stylesheet exclude-result-prefixes="xhtml"
or simply

<html>

Then you need
<xsl:eek:utput method="html"
 
B

Bill Sneddon

I am kind of new at this but you could try.
omit-xml-declaration = "yes"
and put your own <html> and </html> in your transformation.

<xsl:template match="/">
<html>
<xsl:apply-templates/>
</html>
</xsl:template>

Bill
 
C

chris

Martin said:
You can use
<xsl:stylesheet exclude-result-prefixes="xhtml"

I'm just double checking, but that didn't work for me when I tried it.
xsl:transform is synonymous with xsl:stylesheet, right? Ok, it didn't
work. I looked for exclude-result-prefixes on the net, so far it looks
like it should work as you said, but somethings wrong with my sheet and
I don't know what.

Then you need
<xsl:eek:utput method="html"

It still outputs the xmlns:xhtml attribute :(

I think my style sheet must be wrong...




<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xhtml="http://www.w3.org/1999/xhtml"
xmlns="http://www.w3.org/1999/xhtml"
exclude-result-prefixes="xhtml">


<xsl:eek:utput method = "xml"
version = "1.0"
omit-xml-declaration = "no"
encoding = "UTF-8"
indent = "yes"
doctype-public = "-//W3C//DTD XHTML 1.0 Strict//EN"
doctype-system =
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"/>

<xsl:param name="leftDocument">menu.xml</xsl:param>

<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>

<xsl:template match="xhtml:html">
<html>
<xsl:copy-of select="xhtml:head"/>
<body>
<xsl:apply-templates select="xhtml:body"/>
</body>
</html>
</xsl:template>

<xsl:template match="xhtml:body">
<xsl:param name="main">yes</xsl:param>
<xsl:choose>
<xsl:when test="$main='yes'">
<xsl:apply-templates
select="document($leftDocument)/xhtml:html/xhtml:body">
<xsl:with-param name="main">no</xsl:with-param>
</xsl:apply-templates>
<div id="rightcontent">
<xsl:apply-templates />
</div>
</xsl:when>
<xsl:eek:therwise>
<div id="leftcontent">
<xsl:apply-templates />
</div>
</xsl:eek:therwise>
</xsl:choose>
</xsl:template>

<xsl:template match="node()|@*">
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>
 
M

Mike Brown

<xsl:stylesheet version="1.0"

In your stylesheet, you have bound the XHTML namespace URI to the 'xhtml'
prefix, and you have also made it be the default namespace. Remove that
default binding. It is causing all the literal result elements in your
stylesheet to be in that namespace. They get copied into the result tree
with that namespace. When the result tree is serialized, the processor has
to indicate the namespace somehow. exclude-result-prefixes is supposed to
get around this, but it's possible that your processor is getting confused,
perhaps by this:
<xsl:template match="node()|@*">
<xsl:copy-of select="."/>
</xsl:template>

This template matches node() which is any node, and it's at the same
priority as the template that matches "/", I believe. You probably want to
reduce this template's priority (add a priority="-1" attribute). Also, you
probably don't want copy-of in there, because that copies the whole branch
at that node... you want <xsl:copy><xsl:apply-templates
select="node()|@*"/></xsl:copy>, if this is meant to be an identity
transform.

Untested suggestions but I'm just jumping in in the middle here...
 
C

chris

Mike said:
In your stylesheet, you have bound the XHTML namespace URI to the 'xhtml'
prefix, and you have also made it be the default namespace. Remove that
default binding. It is causing all the literal result elements in your
stylesheet to be in that namespace. They get copied into the result tree
with that namespace.

Thanks! That worked but I remember why I added the default namespace...
it now outputs the namespace in elements taken from each of the source
documents.

e.g.

<html>
....
<body>
...
<p xmlns="http://www.w3.org/1999/xhtml">
A more detailed description of the aim of this project can be
found <a href="design/problem.html" shape="rect">here</a> in the
project
<a href="design/index.html" shape="rect">design documentation</a>.
</p>
...
</body>
This template matches node() which is any node, and it's at the same
priority as the template that matches "/", I believe. You probably want to
reduce this template's priority (add a priority="-1" attribute). Also, you
probably don't want copy-of in there, because that copies the whole branch
at that node... you want <xsl:copy><xsl:apply-templates
select="node()|@*"/></xsl:copy>, if this is meant to be an identity
transform.

Changed that too...

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xhtml="http://www.w3.org/1999/xhtml"
exclude-result-prefixes="xhtml">


<xsl:eek:utput method = "xml"
version = "1.0"
omit-xml-declaration = "no"
encoding = "UTF-8"
indent = "yes"
doctype-public = "-//W3C//DTD XHTML 1.0 Strict//EN"
doctype-system =
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"/>

<xsl:param name="leftDocument">menu.xml</xsl:param>

<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>

<xsl:template match="xhtml:html">
<html>
<xsl:copy-of select="xhtml:head"/>
<body>
<xsl:apply-templates select="xhtml:body"/>
</body>
</html>
</xsl:template>

<xsl:template match="xhtml:body">
<xsl:param name="main">yes</xsl:param>
<xsl:choose>
<xsl:when test="$main='yes'">
<xsl:apply-templates
select="document($leftDocument)/xhtml:html/xhtml:body">
<xsl:with-param name="main">no</xsl:with-param>
</xsl:apply-templates>
<div id="rightcontent">
<xsl:apply-templates />
</div>
</xsl:when>
<xsl:eek:therwise>
<div id="leftcontent">
<xsl:apply-templates />
</div>
</xsl:eek:therwise>
</xsl:choose>
</xsl:template>

<xsl:template match="node()|@*" priority="-1">
<xsl:copy><xsl:apply-templates select="node()|@*"/></xsl:copy>
</xsl:template>
</xsl:stylesheet>
 
C

chris

Mike said:
You're implying that when you copy an element, you really don't want an
exact copy; you want to change the name so that it's in no namespace... This
should do it (add it to your stylesheet):

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

Thanks for your help. I get an error when using local-name()...

Error at xsl:element on line 51 of
file:/my-stuff/projects/elena/doc/html/xsl/menu.xsl:
Element name is not a valid QName
Transformation failed: Failed to compile stylesheet. 1 error detected.


Chris
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,994
Messages
2,570,223
Members
46,810
Latest member
Kassie0918

Latest Threads

Top