2009-07-02 64 views
18

我有一些XML其中宣布其仅用于属性的命名空间,就像这样:XSL - 复制元素,但删除未使用的命名空间(S)

<?xml version="1.0" encoding="UTF-8"?> 
<a xmlns:x="http://tempuri.com"> 
    <b> 
     <c x:att="true"/> 
     <d>hello</d> 
    </b> 
</a> 

我想使用XSL来创建一个副本选定节点及其值 - 消除属性。所以我期望的输出是:

<?xml version="1.0" encoding="UTF-8"?> 
<b> 
    <c /> 
    <d>hello</d> 
</b> 

我有一些XSL,几乎做到这一点,但我似乎无法阻止它把空间声明输出的顶级元素。我的XSL是:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:template match="/"> 
     <xsl:apply-templates select="https://stackoverflow.com/a/b"/> 
    </xsl:template> 

    <xsl:template match="node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="node()"/> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

输出的第一个元素是<b xmlns:x="http://tempuri.com">而不是<b>。我试过在XSL中声明名称空间,并将前缀放在exclude-result-prefixes列表中,但这似乎没有任何作用。我究竟做错了什么?

更新:我发现通过在XSL中声明命名空间并使用extension-element-prefixes属性工作,但这看起来不正确!我想我可以使用这个,但我想知道为什么exclude-result-prefixes不起作用!

更新:实际上,似乎这个extension-element-prefixes解决方案只适用于XMLSpy的内置XSLT引擎,而不适用于MSXML。

回答

9
<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" 
    xmlns:x="http://tempuri.com"> 
    <xsl:template match="/"> 
     <xsl:apply-templates select="https://stackoverflow.com/a/b"/> 
    </xsl:template> 

    <xsl:template match="*"> 
     <xsl:element name="{local-name(.)}"> 
      <xsl:apply-templates/> 
     </xsl:element> 
    </xsl:template> 

    <xsl:template match="@*"> 
     <xsl:copy/> 
    </xsl:template> 

    <!-- This empty template is not needed. 
Neither is the xmlns declaration above: 
    <xsl:template match="@x:*"/> --> 
</xsl:stylesheet> 

我找到了一个解释here

迈克尔·凯说:
排除对结果的前缀只影响一个字面结果元素从 样式复制的命名空间,它不从源文件影响的 命名空间复制。

+0

谢谢,这样没有问题(虽然“@ *”模板似乎并没有被要求),但我认为“本地名( )“功能很慢..? – 2009-07-03 07:28:15

5
<xsl:stylesheet 
    version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:x="http://tempuri.com" 
    exclude-result-prefixes="x" 
> 

    <!-- the identity template copies everything 1:1 --> 
    <xsl:template match="@* | node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@* | node()" /> 
    </xsl:copy> 
    </xsl:template> 

    <!-- this template explicitly cares for namespace'd attributes --> 
    <xsl:template match="@x:*"> 
    <xsl:attribute name="{local-name()}"> 
     <xsl:value-of select="." /> 
    </xsl:attribute> 
    </xsl:template> 

</xsl:stylesheet> 
2

这将从输出中删除在x命名空间。

<xsl:namespace-alias result-prefix="#default" stylesheet-prefix="x" /> 

记住在处理默认名称空间时要做两件事。首先将其映射到样式表标签中的某些内容,然后使用名称空间别名将其删除。

4

试试这个(注意属性copy-namespaces='no'):

<xsl:template match="node()"> 
    <xsl:copy copy-namespaces="no"> 
      <xsl:apply-templates select="node()"/> 
    </xsl:copy> 
</xsl:template>