Reputation: 686
I'm stuck on what I think should be simple thing to do. I've been looking around, but didn't find the solution. Hope you will help me.
What I have is an XML element with an attribute that contains escaped HTML elements:
<Booking>
<BookingComments Type="RAM" comment="RAM name fred<br/>Tel 09876554<br/>Email [email protected]" />
</Booking>
What I need to get is parsed HTML elements and content from the @comment attribute to be a content of
element as follows:
<p>
RAM name fred<br/>Tel 09876554<br/>Email [email protected]
<p>
Here is my XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" exclude-result-prefixes="xs fn" version="1.0">
<xsl:output method="html" doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN"
doctype-system="http://www.w3.org/TR/html4/loose.dtd" encoding="UTF-8" indent="yes" />
<xsl:template name="some-template">
<p>Some text</p>
<p>
<xsl:copy-of
select="/Booking/BookingComments[lower-case(@Type)='ram'][1]/@comment"/>
</p>
</xsl:template>
</xsl:stylesheet>
I've read that copy-of is a good way to restore escaped HTML elements back to proper elements. In this specific case, because it's initially an attribute the copy-of translates it into attribute as well. So I get:
<p comment="RAM name fred<br/>Tel 09876554<br/>Email [email protected]"></p>
Which isn't what I want.
If I use apply-templates instead of copy-of, as in:
<p>
<xsl:apply-templates select="/Booking/BookingComments[lower-case(@Type)='ram'[1]/@comment"/>
</p>
I get p's content simply as text, not restored HTML elements.
<p>RAM name fred<br/>Tel 09876554<br/>Email [email protected]</p>
I'm sure I'm missing something obvous. I would really appreciate any help and tips!
Upvotes: 4
Views: 4343
Reputation: 25956
You could bind an extension function parse() which parses a string into a nodeset. The exact mechanism will depend on your XSLT engine.
In Xalan, we can take the following static method:
public class MyExtension
{
public static NodeIterator Parse( string xml );
}
and use it like so:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:java="http://xml.apache.org/xalan/java"
exclude-result-prefixes="java"
version="1.0">
<xsl:template match="BookingComments">
<xsl:copy-of select="java:package.name.MyExtension.Parse(string(@comment))" />
</xsl:template>
</xsl:stylesheet>
Upvotes: 1
Reputation: 338316
I would recommend using a dedicated template:
<!-- check if lower-casing @Type is really necessary -->
<xsl:template name="BookingComments[lower-case(@Type)='ram']/@comment">
<p>
<xsl:value-of select="." disable-output-escaping="yes" />
</p>
</xsl:template>
This way you could simply apply templates to the attribute. Note that disabling output escaping has the potential to generate ill-formed output.
Upvotes: 4