2010-09-30 194 views
4

在网上寻找答案后,提出“几乎”的解决方案......我决定将问题简化为一个非常简单的案例。未使用的命名空间声明出现在XSLT后

考虑下面的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出现p元素里面?

无论我尝试了什么,我都无法让东西上班。我有一个奇怪的感觉,问题是我的xsl:copy-of声明。

+0

好问题(+1)。查看我的答案以获得详细的解释和完整的解决方案。 – 2010-09-30 04:44:38

回答

6

我有一种奇怪的感觉, 问题是我xsl:copy-of 声明。

正是这个原因。

源XML文档包含该片段

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

在XPath数据模型,命名空间节点从一个子树的给其所有后代的根部繁殖。因此,<p>元件具有以下名称空间:

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

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

  3. 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> 
+0

即使您尝试过,也不会更有帮助。谢谢迪米特雷 - 很好的解释。恰到好处。 – Isaac 2010-09-30 05:32:39

+0

但是,我意识到这个解决方案存在一个缺陷:HTML元素中的属性不会被复制......所以我现在正试图解决这个问题。 – Isaac 2010-09-30 05:50:27

+1

@Isaac:我刚刚编辑我的答案,以复制元素的所有属性。您可以在此处使用''而不是'',这样可以提供更多灵活性 - 您可以使用模板来处理特定属性。 – 2010-09-30 12:41:37