代码之家  ›  专栏  ›  技术社区  ›  Isaac

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

  •  4
  • Isaac  · 技术社区  · 14 年前

    在搜索了答案后,提出了“几乎”的解决方案…我决定把这个问题简化成一个非常简单的例子。

    请考虑以下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的名称空间,这是此文档的默认名称空间。

    现在考虑下面的简单样式表。我想创建一个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 出现在 元素?

    不管我做了什么,我都不能让东西工作。我有种奇怪的感觉,问题出在我的 xsl:copy-of 语句。

    1 回复  |  直到 10 年前
        1
  •  6
  •   Dimitre Novatchev    14 年前

    我有一种奇怪的感觉 我的问题是 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/

    最后两个是 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>