将节点的内容克隆到不同的命名空间

时间:2010-06-29 19:14:06

标签: html xslt namespaces

在获得有关真实情况的更多知识后,我更新了原始问题的标题和文字。我误解了这个症状,因为空白没有被保留,而真正发生的是HTML元素没有被解释为HTML。

我正在编写从WADL文档到HTML的转换。我需要克隆WADL <doc>元素的内容,同时保留空格,因为<doc>元素可能包含像<pre>这样的HTML元素,它们在更改命名空间时关心空白到HTML。

示例WADL <doc>元素:

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

以下是我目前正在改变的方式:

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

我所看到的是复制的<pre>元素的内容已经折叠的空白不被解释为<pre>元素,因此表示样本看起来走出低谷,重新振作起来,重整旗鼓。在复制<doc>元素的内容时,如何指示XSL输出保留空格覆盖命名空间?或者这只是我选择<doc>元素内容的方式的问题?

更新

在勾选出这可能是输出命名空间问题后,我创建了以下最小化设置进行试验:

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>

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>

当我检查Firefox上的<p><pre>元素的DOM节点时,元素的命名空间指向WADL命名空间,并且它们无法正确呈现为HTML(它们看起来像像纯文本一样)。当我在Chrome上执行相同操作时,命名空间是XHTML,元素呈现为正确的XHTML元素。

所以,我猜,因为在原始WADL文档的<doc>元素中我没有明确使用名称空间前缀,我需要找到一种强制使用<doc>内容的好方法XHTML命名空间,或者只是在<doc>的内容中添加一个XHTML名称空间前缀(更多工作,但似乎是正确的方法)。

2 个答案:

答案 0 :(得分:1)

我无法使用提供的XSLT代码重现问题

我稍微修改了它,添加了wadl:命名空间:

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

在此XML文档上应用此转换时

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

使用所需的空格生成结果

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

我怀疑您的浏览器在自定义命名空间中时可能无法正确解释<pre>(IE并不介意)。

请注意我的转换中的命名空间剥离。如果单独使用命名空间剥离不会在浏览器中产生所需的结果,则需要创建<pre>(和任何其他html标记通过使用

在(X)Html命名空间中从源XML文档复制

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

指令。

答案 1 :(得分:1)

在Dimitre回答之后,当我运行这个样式表时:

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

使用您的更新输入文档:

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

我在Firefox 3.5.9上获得此输出(来自“Inspect element”选项):

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

注意:在Firefox中,如果转换未输出正确的HTML或XHTML,则会在transformix元素内输出。但这似乎与保留的空白区域没有关系(至少在这个版本中)。

修改pre/@id属于我为“@ *”模板测试过的其他输入。对不起