2013-04-26 134 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>