开发者

Clone contents of node into different namespace

开发者 https://www.devze.com 2023-01-05 16:10 出处:网络
I\'ve updated the title and the text of my original question after gaining more knowledge on what\'s really going on. I misinterpreted the symptom as whitespace not being preserved while what\'s reall

I've updated the title and the text of my original question after gaining more knowledge on what's really going on. I 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 experimen开发者_如何学编程t 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">
    <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">
<xsl:output
    doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
    doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"/>
<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).


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">

instruction.


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"/>

<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">
        <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">   
    <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

0

精彩评论

暂无评论...
验证码 换一张
取 消