XSLT transformation to produce valid XHTML: a namespace issue
I have seen this resource link text but I still have troubles generating a valid XHTML document using MSXML parser.
I have in input the following document:
<?xml version="1.0" encoding="UTF-8" ?>
- <html xml:lang="it" xmlns="http://www.w3.org/1999/xhtml">
- <head xmlns="">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Bla bla bla</title>
<link rel="stylesheet" type="text/css" media="screen" href="css/bla.css" />
</head>
- <body xmlns="" style="background-color:#DFDFDF;left-margin:0;margin-top:0">
....
</body>
</html>
where the nasty xmlns="" are produced because i have inserted the instruction:
parserInstance.documentElement.setAttribute "xmlns", "http://www.w3.org/1999/xhtml"
when creating the input document before transformation.
The XSLT imports the transformation I use for catching the html elements
<xsl:stylesheet
version="1.0"
xmlns:xhtml="http://www.w3.org/1999/xhtml"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
exclude-result-prefixes="xhtml xsl"
>
<xsl:import href="_lib.xsl"/>
<xsl:import href="_standard.xsl"/>
and within _standard.xsl I have the code that make the rerlevant transformation:
<xsl:template match="html">
<xsl:copy>
<xsl:copy-of select="@*" />
<xsl:apply-templates select="head" />
<xsl:apply-templ开发者_JS百科ates select="body" />
</xsl:copy>
Still I do not have the required xmlns in the html markup:
<html xml:lang="it">
AND I still have the nasty xmlns intersparsed in html code:
<h1 xmlns="http://www.w3.org/1999/xhtml">BLA BLA</h1>
Where I am getting wrong?
Please, NOTE: i MUST use a pull model for transformation, I cannot use an identity transform
With the DOM model (MSXML uses) the namespace of an element or attribute node is determined when it is created, you can't change it afterwards and attempts like yours to change namespaces by setting an attribute with name "xmlns" do not change the namespace of nodes.
So it sounds as if you have an input document with elements in no namespace and want to use XSLT to transform it into one with elements in the XHTML namespace. In that case you can't use xsl:copy as that way you get result elements in no namespace. Instead you need e.g.
<xsl:template match="html">
<html xmlns="http://www.w3.org/1999/xhtml">
...
</html>
</xsl:template>
or of course as you want that namespace for all result elements you could put xmlns="http://www.w3.org/1999/xhtml" on the xsl:stylesheet element of the stylesheet or stylesheet module(s) that you want to create XHTML elements.
If you put xmlns="http://www.w3.org/1999/xhtml" on the 'html' element then it applies to that element and all its (not qualified) descendant elements. The 'body' element is in a completely different template so you either need to put a namespace declaration on the body element too or, as already suggested, you simply put xmlns="http://www.w3.org/1999/xhtml" on all xsl:stylesheet elements of your stylesheet modules that are supposed to create XHTML elements.
And also not that doing or will create a copy of the input node. As your input elements are in no namespace if you copy any of them the copy in the result will also be in no namespace while you want the result elements to be in the XHTML namespace. Thus doing xsl:copy or xsl:copy-of will not work for what you want, instead you need to run your elements through a template that changes the namespace e.g.
<xsl:template match=*">
<xsl:element name="{local-name()}" namespace="http://www.w3.org/1999/xhtml">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
@Martin: I am posting samples. Sorry to have been generic in my comment.
Input document (minimal)
<?xml version="1.0" encoding="UTF-8"?>
<html xml:lang="it">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>Page title</title>
<link rel="stylesheet" type="text/css" media="screen" href="css/stile.css"/>
</head>
<body>
<div id="errorPanel" class="errorPanel"/>
<navigation>
<panel name="navbar">
<link>
<url>resource1.htm</url>
<label>resource1</label>
</link>
</panel>
<panel name="special">
<link>
<url>resource2.htm</url>
<label>resource2</label>
</link>
</panel>
</navigation>
<content/>
<script type="text/javascript" src="lib/jquery.js"/>
<script type="text/javascript" src="backend.js"/>
</body>
</html>
Then the main XSL just for content:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/1999/xhtml"
exclude-result-prefixes="xsl"
>
<xsl:import href="_lib.xsl"/>
<xsl:import href="_standard.xsl"/>
<xsl:output
method="xml"
omit-xml-declaration="no"
encoding="UTF-8"
doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
/>
<xsl:template match="content">
<h1>CONTENT</h1>
<p>
Bla bla bla
</p>
</xsl:template>
</xsl:stylesheet>
Then _standard.xsl. Note, the instruction:
<xsl:template match="html">
is used temporarily, the xsl-copy was used as in the first code snippet posted
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:template match="html">
<html xmlns="http://www.w3.org/1999/xhtml">
<xsl:copy-of select="@*" />
<xsl:apply-templates select="head" />
<xsl:apply-templates select="body" />
</html>
</xsl:template>
<xsl:template match="head">
<xsl:copy-of select="." />
</xsl:template>
<xsl:template match="body">
<body>
<table id='toppanel'>
<tr>
<td>Bla bla bla</td>
<td>Bla bla bla</td>
<td>Bla bla bla</td>
</tr>
</table>
<table>
<tr>
<xsl:apply-templates select="navigation/panel[@name='navbar']" mode="td"/>
</tr>
</table>
<table>
<tr>
<td>
<p>Area</p>
<xsl:apply-templates select="navigation/panel[@name='special']" />
</td>
<td>
<xsl:apply-templates select="content" />
</td>
</tr>
</table>
</body>
</xsl:template>
</xsl:stylesheet>
I have found in the output markup like this:
<body xmlns="">
Hope is clear.
精彩评论