views:

105

answers:

2

I've updated the title and the text of my original question after gaining more knowledge on what's really going on. The misinterpreted the symptom as whitespace not being preserved while what's really going on was that the HTML elements weren't being interpreted as HTML.

I'm writing a transformation from a WADL document to HTML. I need to clone the contents of WADL <doc> elements while preserving whitespace because the <doc> elements may contain HTML elements like <pre> that care about whitespace while changing the namespace to HTML.

Sample WADL <doc> element:

<doc xml:lang="en" title="Some Representation">
    Sample representation:
    <pre><![CDATA[
        <MyRoot>
            <MyChild awesome="yes"/>
        </MyRoot>
    ]]></pre>
</doc>

Here's how I'm currently transforming this:

<xsl:apply-templates select="wadl:doc"/>

...

<xsl:template match="wadl:doc">
    <xsl:if test="@title">
        <p><strong><xsl:value-of select="@title"/></strong></p>
    </xsl:if>
    <p><xsl:copy-of select="*|node()"/></p>
</xsl:template>

What I'm seeing is that the contents of the copied <pre> element has the whitespace collapsed isn't interpreted as a <pre> element and therefore the representation sample looks out of whack. How can I instruct XSL output to preserve the whitespace override the namespace while copying the contents of <doc> elements? Or is this simply a problem with the way I select the contents of the <doc> elements?

Update

After being ticked off that this could be an output namespace issue, I created the following minimal setup to experiment on:

The XML:

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="doc_test.xsl"?>
<application xmlns="http://wadl.dev.java.net/2009/02"&gt;
    <doc>
        <p>This is an HTML paragraph</p>
        <pre>
And this
is a
preformatted
block of
text.
        </pre>
    </doc>
</application>

The XSL:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:wadl="http://wadl.dev.java.net/2009/02"&gt;
<xsl:output
    doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
    doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"/&gt;
<xsl:template match="wadl:application">
<html>
<head>
    <title>Doc Test</title>
</head>
<body>
<xsl:apply-templates select="wadl:doc"/>
</body>
</html>
</xsl:template>

<xsl:template match="wadl:doc">
    <xsl:copy-of select="node()"/>
</xsl:template>

</xsl:stylesheet>

When I inspect the DOM node of the <p> or <pre> elements on Firefox, the namespace of the elements point to the WADL namespace, and they don't get properly rendered as HTML (they look like plain text). When I do the same on Chrome, the namespace is XHTML and the elements render as proper XHTML elements.

So, I guess, since in the <doc> elements of my original WADL document I'm not using namespace prefixes explicitly, I need to find a nice way to force the contents of <doc> to use the XHTML namespace, or simply add an XHTML namespace prefix to the contents of <doc> (more work, but seems to be the proper way).

+1  A: 

I cannot repro the problem using the provided XSLT code.

I have modified it slightly, adding the wadl: namespace:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:wadl="some:wadl-namespace"
  exclude-result-prefixes="wadl"
 >
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

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

 <xsl:template match="wadl:doc">
    <xsl:if test="@title">
        <p><strong><xsl:value-of select="@title"/></strong></p>
    </xsl:if>
    <p><xsl:apply-templates select="node()"/></p>
 </xsl:template>

 <xsl:template match="wadl:pre">
   <pre>
     <xsl:apply-templates select="node()"/>
   </pre>
 </xsl:template>

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

when this transformation is applied on this XML document:

<doc xml:lang="en" title="Some Representation"
  xmlns="some:wadl-namespace"
>
    Sample representation:
    <pre><![CDATA[
        <MyRoot>
            <MyChild awesome="yes"/>
        </MyRoot>
    ]]></pre>
</doc>

the result is produced with the desired whitespace:

<p><strong>Some Representation</strong></p>
<p>
    Sample representation:
    <pre>
        &lt;MyRoot&gt;
            &lt;MyChild awesome="yes"/&gt;
        &lt;/MyRoot&gt;
    </pre>
</p>

I suspect that your browser may not interpret correctly <pre> when it is in a custom namespace (IE doesn't mind that).

Do note the namespace stripping in my transformation. If namespace stripping alone does not produce the desired results in your browser, you'll need to create <pre> (and any other html tags copied from the source XML document) in the (X)Html namespace, by using the

<xsl:element name="{name()}" namespace="http://www.w3.org/1999/xhtml"&gt;

instruction.

Dimitre Novatchev
I tested this on multiple browsers and only Firefox seems to have this issue. Things work as I expect on IE, Chrome, Safari and Opera. Yes, it could be that Firefox is sensitive to custom/missing namespace of the HTML elements that get copied over. When I view the DOM with Firebug, the `<pre>` elements looks grayed out. I'll see if I can fix the namespace issue.
Ates Goral
I've created a minimal setup based on my own setup to recreate the issue. Now I'll start applying some of the techniques that you've used in your answer until I resolve the namespace issue.
Ates Goral
Thanks! Everything is clear in my head now. I'll either change the WADL documents to explicitly use an XHTML namespace prefix inside `<doc>` elements or apply your namespace stripping technique to force the XHTML namespace upon the `<doc>` contents.
Ates Goral
BTW `exclude-result-prefixes="wadl"` doesn't help with Firefox.
Ates Goral
I've used a template to copy the `<doc>` contents with `<xsl:element namespace>` to override the namespace and that solved my problem. Thanks for the big nudge in the right direction!
Ates Goral
@Ates-Goral: I am glad that I could help. You are always welcome.
Dimitre Novatchev
+1  A: 

Following Dimitre answer, when I run this stylesheet:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:wadl="http://wadl.dev.java.net/2009/02"
    xmlns="http://www.w3.org/1999/xhtml"
    exclude-result-prefixes="wadl">
<xsl:output method="xml" omit-xml-declaration="yes"
    doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
    doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"/&gt;

<xsl:template match="wadl:application">
<html>
<head>
    <title>Doc Test</title>
</head>
<body>
<xsl:apply-templates select="wadl:doc/node()"/>
</body>
</html>
</xsl:template>

<xsl:template match="*">
    <xsl:element name="{name()}" namespace="http://www.w3.org/1999/xhtml"&gt;
        <xsl:apply-templates select="@*|node()"/>
    </xsl:element>
</xsl:template>

<xsl:template match="@*">
    <xsl:copy/>
</xsl:template>

</xsl:stylesheet>

With your update input document:

<application xmlns="http://wadl.dev.java.net/2009/02"&gt;   
    <doc>   
        <p>This is an HTML paragraph</p>   
        <pre>   
And this   
is a   
preformatted   
block of   
text.   
        </pre>   
    </doc>   
</application>   

I get this output on Firefox 3.5.9 (from "Inspect element" option):

<html><head><title>Doc Test</title></head><body>
        <p>This is an HTML paragraph</p>
        <pre>
And this
is a
preformatted
block of
text.
        </pre>
    </body></html>

Note: In Firefox, if your transformation didn't output a proper HTML or XHTML, it will output inside a transformix element. But this seems to have no relationship with preserved white spaces (at least in this version).

Edit: The pre/@id belong to other input that I've tested for the '@*' template. Sorry

Alejandro
+1 Thanks Alejandro! I've also applied the same namespace replacement and that solved my problem. Your implementation looks more concise than mine though. Thanks! I'm still keeping Dimitre's answer as the accepted answer because I solved my problem on my own after the information he gave in his answer.
Ates Goral
@Ates Goral: I'm just glad that you find this test case for Firefox helpfull. That was the point.
Alejandro