Reputation:
I am using xslt to transform an xml file to html. The .net xslt engine keeps serving me self-closing tags for empty tags.
Example:
<div class="test"></div>
becomes
<div class="test" />
The former is valid html, while the latter is illegal html and renders badly. My question is : How do I tell the xslt engine (XslCompiledTransform) to not use self-closing tags.
If it's not possible, how can I tell my browser (IE6+ in this case) to interpret self-closing tags correctly.
Upvotes: 26
Views: 23690
Reputation: 3932
Don't try this at home:
<xsl:when test="self::* and not(text())">
<xsl:value-of select="concat('<', name(), '>', '</', name(), '>')" disable-output-escaping="yes"/>
</xsl:when>
Upvotes: 0
Reputation: 527
The easy way I found was creating a new XmlTextWriter class to override the method WriteEndElement, forcing the non-closing tag and pass on the serialization process as parameter.
public class MyXmlTextWriter : XmlTextWriter
{
public MyXmlTextWriter(Stream stream) : base(stream, Encoding.UTF8)
{ }
public MyXmlTextWriter(TextWriter stream) : base(stream)
{ }
public override void WriteEndElement()
{
base.WriteFullEndElement();
}
}
Upvotes: 2
Reputation: 103358
I use the following whenever I wish to prevent an element from self-closing:
<xsl:value-of select="''" />
This fools the rendering engine into believe there is content inside the element, and therefore prevents self-closure.
It's a bit of an ugly fix so I recommend containing it in a descriptive template and calling that each time instead:
<xsl:template name="PreventSelfClosure">
<xsl:value-of select="''" />
</xsl:template>
<div class="test">
<xsl:call-template name="PreventSelfClosure"/>
</div>
This will then render the following:
<div class="test"></div>
http://curtistimson.co.uk/post/xslt/how-to-prevent-self-closing-elements-in-xslt/
Upvotes: 0
Reputation: 3846
There are a few things you need to be careful:
This is a piece of working code:
string xmlStr = "<?xml version='1.0' encoding='UTF-8'?><Data></Data>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xmlStr);
string xslContents = @"
<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
xmlns:msxsl='urn:schemas-microsoft-com:xslt' exclude-result-prefixes='msxsl'>
<xsl:output method='html' version='4.0' omit-xml-declaration='yes' indent='yes'/>
<xsl:template match='Data'>
<html>
<body>
<div></div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>";
XslCompiledTransform xsl = new XslCompiledTransform();
xsl.Load(XmlReader.Create(new StringReader(xslContents)));
StringWriter result = new StringWriter();
using (XmlWriter writer = XmlWriter.Create(result, xsl.OutputSettings))
{
xsl.Transform(doc, null, writer);
}
System.Diagnostics.Debug.Write( result.ToString());
Upvotes: 1
Reputation: 1890
Just experienced the same issue with PHP 5's XSL, with output/@method=html. Seems that assigning an empty value attribute will cause elements to be output as invalid non-self-closing, non-closed tags:
<input type="text" name="foo" value="{my-empty-value}" />
results in:
<input type="text" name="foo" value="">
One possible solution is to conditionally add the attribute:
<xsl:if test="string-length(my-empty-value) > 0">
<xsl:attribute name="value">
<xsl:value-of select="my-empty-value" />
</xsl:attribute>
</xsl:if>
resulting in:
<input type="text" name="foo" />
Upvotes: 0
Reputation: 3610
A workaround can be to insert a comment element to force generation of non self closing:
<script type="text/javascript" src="nowhere.js">
<xsl:comment></xsl:comment>
</script>
It is not a pretty soloution, but it works :-)
/Sten
Upvotes: 18
Reputation: 3743
I used to put an <xsl:text>
element inside, like:
<script type="text/javascript" src="/scripts/jquery.js"><xsl:text> </xsl:text></script>
Upvotes: 2
Reputation: 31
For me it was a problem in the script tag. I solved it by filling it with a semicolon (;)
<script type="text/javascript" src="somewhere.js">;</script>
Upvotes: 3
Reputation: 4433
This is related to the XslCompiledTransform class
here is a workaround:
Upvotes: 4
Reputation: 1982
If you are using XmlWriter as your ouput stream, use HTMLTextWriter instead. XMLWriter will reformat your HTML output back to XML.
Upvotes: 12
Reputation: 20784
You can't tell your browser to handle invalid HTML as HTML -- you're lucky it understands malformed HTML at all. :)
Definitely do this in your stylesheet:
<xsl:output method="html"/>
But, if your source document has namespaces, this won't do the trick. XSLT processors seem to silently change the output method back to XML if namespace nodes are present in the output.
You need to replace all instances of <xsl:copy-of>
and <xsl:copy>
with creations of elements with just the local name, e.g.
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
See
etc.
Upvotes: 2
Reputation: 29576
Change your xsl:output
method to be html
(instead of xml
).
Or add it if you haven't already got the element
<xsl:output method="html"/>
Upvotes: 25