2013-04-26 122 views
0

使用XSLT,我想美化我的XML并提取名称空间声明并使用前缀。使用XSLT将XML名称空间转换为顶级前缀

我:

<a xmlns="ns1"> 
    <b xmlns="ns2"> 
     <c xmlns="ns3"/> 
    </b> 
</a> 

我想:

<a xmlns="ns1" xmlns:b="ns2" xmlns:c="ns3"> 
    <b:b> 
     <c:c/> 
    </b:b> 
</a> 

在一个步骤中自动执行此操作将是困难的。所以我想到了多个步骤。每个命名空间一个。

我试图使用namespace="{namespace-uri(.)}"但我无法将名称空间拉到根元素。

+0

你怎么想,以确定哪些前缀ŧ o使用? – JLRishe 2013-04-26 10:00:56

回答

2

似乎没有在你的选择,在你的榜样命名空间前缀的任何逻辑清晰,所以我认为这将是很难实现的,但在这里是如何做同样的事情:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       xmlns:exslt="http://exslt.org/common" 
       exclude-result-prefixes="exslt"> 
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/> 
    <xsl:key name="kNs" match="*[namespace-uri()]" use="namespace-uri()" /> 

    <!-- Build a list of elements to represent all namespaces --> 
    <xsl:variable name="uniqueNsNf"> 
    <xsl:for-each select="//*[generate-id() = 
           generate-id(key('kNs', namespace-uri())[1])]"> 
     <xsl:element name="ns{position()}:ns" namespace="{namespace-uri()}" /> 
    </xsl:for-each> 
    </xsl:variable> 
    <xsl:variable name="uniqueNs" select="exslt:node-set($uniqueNsNf)/*" /> 

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

    <xsl:template match="*[namespace-uri()]"> 
    <xsl:variable name="nsMap" 
        select="$uniqueNs[namespace-uri() = 
            namespace-uri(current())]" /> 
    <xsl:element name="{substring-before(name($nsMap), ':')}:{local-name()}" 
       namespace="{namespace-uri()}"> 
     <xsl:copy-of select="$uniqueNs/namespace::*"/> 
     <xsl:apply-templates select="@* | node()" /> 
    </xsl:element> 
    </xsl:template> 
</xsl:stylesheet> 

<a xmlns="ns1"> 
    <b xmlns="ns2"> 
    <c xmlns="ns3"/> 
    <b xmlns="ns2" /> 
    </b> 

    <d xmlns="otherNs"> 
    <b xmlns="ns3" /> 
    </d> 
</a> 

的结果是:如果这是在接下来的输入运行

<ns1:a xmlns:ns1="ns1" xmlns:ns2="ns2" xmlns:ns3="ns3" xmlns:ns4="otherNs"> 
    <ns2:b> 
    <ns3:c /> 
    <ns2:b /> 
    </ns2:b> 

    <ns4:d> 
    <ns3:b /> 
    </ns4:d> 
</ns1:a>