在XSLT之后出现未使用的命名空间声明

时间:2010-09-30 04:00:52

标签: xml xslt namespaces

在网上寻找答案后,提出“差不多”的解决方案......我决定将问题简化为一个非常简单的案例。

请考虑以下XML代码段:

<me:root xmlns:me="http://stackoverflow.com/xml"
  xmlns="http://www.w3.org/1999/xhtml">
    <me:element>
        <p>Some HTML code here.</p>
    </me:element>
</me:root>

请注意,p元素是XHTML的命名空间,这是此doc的默认命名空间。

现在考虑以下简单的样式表。我想创建一个XHTML文档,其内容为me:element

<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:me="http://stackoverflow.com/xml"
  xmlns="http://www.w3.org/1999/xhtml"
  exclude-result-prefixes="me">
    <xsl:template match="/">
        <html xmlns="http://www.w3.org/1999/xhtml">
            <head>
                <title>My Title</title>
            </head>
            <body>
                <xsl:copy-of select="me:root/me:element/node()"/>
            </body>
        </html>
    </xsl:template>
</xsl:stylesheet>

请注意,我添加了exclude-result-prefixes ...但是看看我得到了什么:

<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>My Title</title>
    </head>
    <body>
        <p xmlns:me="http://stackoverflow.com/xml">Some HTML code here.</p>
    </body>
</html>

这让我疯狂的是为什么,为什么xmlns:me出现在p元素内?

无论我尝试什么,我都无法上班。我有一种奇怪的感觉,问题出在我的xsl:copy-of声明中。

1 个答案:

答案 0 :(得分:6)

  我有一种奇怪的感觉   问题出在我的xsl:copy-of   言。

这正是原因。

源XML文档包含此片段

<me:element> 
    <p>Some HTML code here.</p> 
</me:element> 

在XPath数据模型中,命名空间节点从子树的根传播到其所有后代。因此,<p>元素具有以下名称空间:

  1. "http://www.w3.org/1999/xhtml"

  2. "http://stackoverflow.com/xml"

  3. "http://www.w3.org/XML/1998/namespace"

  4. http://www.w3.org/2000/xmlns/

  5. 最后两个是 reserved namespaces (对于前缀xml:xmlns),可供任何指定节点使用。

    报告的问题是由于定义<xsl:copy-of>指令将所有节点及其完整子树复制到属于每个节点的所有名称空间。

    请记住:指定为exclude-result-prefixes属性值的前缀仅从文字结果元素中排除!

    <强>解决方案

    <xsl:stylesheet version="2.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:me="http://stackoverflow.com/xml"
      xmlns="http://www.w3.org/1999/xhtml"
      exclude-result-prefixes="me">
    
      <xsl:output method="xml" omit-xml-declaration="yes"
      indent="yes"/>
      <xsl:strip-space elements="*"/>
    
        <xsl:template match="/">
         <html xmlns="http://www.w3.org/1999/xhtml">
          <head>
            <title>My Title</title>
          </head>
          <body>
            <xsl:apply-templates select="me:root/me:element/*"/>
          </body>
         </html>
        </xsl:template>
    
        <xsl:template match="*">
          <xsl:element name="{name()}">
           <xsl:copy-of select="@*"/>
           <xsl:apply-templates/>
          </xsl:element>
        </xsl:template>
    </xsl:stylesheet>
    

    将此转换应用于提供的XML文档

    <me:root xmlns:me="http://stackoverflow.com/xml"
      xmlns="http://www.w3.org/1999/xhtml">
        <me:element>
            <p>Some HTML code here.</p>
        </me:element>
    </me:root>
    

    产生了想要的正确结果

    <html xmlns="http://www.w3.org/1999/xhtml">
       <head>
          <title>My Title</title>
       </head>
       <body>
          <p>Some HTML code here.</p>
       </body>
    </html>