2010-11-18 49 views
3

元素我有這樣的XML:重命名XSLT

<pos:getPositionRouter xmlns:pos="positionNS"> 
    <positionID> 
     <code>1</code> 
    </positionID> 
    <parameter>?</parameter> 
</pos:getPositionRouter> 

,我想使用XSLT元素命名pos:getPositionRouterx:getPosition

<x:getPosition xmlns:x="newPositionNS"> 
    <positionID> 
     <code>1</code> 
    </positionID> 
    <parameter>?</parameter> 
</x:getPosition> 

這是我想出了sylesheet:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

<xsl:output method="xml" omit-xml-declaration="yes" indent="yes" /> 

<xsl:param name="old_namespace" /> 
<xsl:param name="old_element_localname" /> 
<xsl:param name="new_namespace" /> 
<xsl:param name="new_element_localname" /> 


<xsl:template match="@*|node()"> 
    <xsl:choose> 
    <xsl:when test="(local-name() = $old_element_localname) and (namespace-uri() = $old_namespace)"> 
    <xsl:element name="{$new_element_localname}" namespace="{$new_namespace}"> 
    <xsl:apply-templates select="@*|node()"/> 
    </xsl:element> 
    </xsl:when> 

    <!-- copy the rest as is --> 
    <xsl:otherwise> 
    <xsl:copy> 
    <xsl:apply-templates select="@*|node()" /> 
    </xsl:copy> 
    </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

</xsl:stylesheet> 

我不得不使用xalan作爲xslt處理器,輸出結果不幸的是這樣的:

<getPosition xmlns="newPositionNS"> 
    <positionID xmlns:pos="positionNS"> 
     <code>1</code> 
    </positionID> 
    <parameter xmlns:pos="positionNS">?</parameter> 
</getPosition> 

getPosition元素的默認命名空間成爲新的命名空間,但子元素應該仍然沒有命名空間(xmlns="")。

有人能理解爲什麼嗎?

謝謝!

+0

請注意,您的期望輸出和實際輸出在語義上是平等的:'{} newPositionNS兒童getPosition'正在空命名空間URI,他們只是有一個「positionNS」命名空間URI的範圍(但未使用)。 – 2010-11-18 16:13:57

+0

你好Alejandro,據我所知,兩個輸出在語義上並不相同:根元素上的默認名稱空間設置xmlns =「newPositionNS」被繼承到子元素,所以positionID現在位於newPositionNS名稱空間中,而不是「 「命名空間,因爲它應該。 – Simon 2010-11-18 16:26:59

+0

好問題,+1。看到我的答案是一個簡短而簡單的解決方案。 :) – 2010-11-18 16:54:03

回答

1

這個樣式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:param name="old_namespace" select="'positionNS'"/> 
    <xsl:param name="old_element_localname" select="'getPositionRouter'"/> 
    <xsl:param name="new_namespace_prefix" select="'x'"/> 
    <xsl:param name="new_namespace" select="'newPositionNS'"/> 
    <xsl:param name="new_element_localname" select="'getPosition'" /> 
    <xsl:template match="*"> 
     <xsl:choose> 
      <xsl:when test="local-name()=$old_element_localname and 
          namespace-uri()=$old_namespace"> 
       <xsl:element 
        name="{substring(concat($new_namespace_prefix,':'), 
             1 div boolean($new_namespace_prefix))}{ 
          $new_element_localname}" 
        namespace="{$new_namespace}"> 
        <xsl:apply-templates select="@*|node()"/> 
       </xsl:element> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:element name="{name()}"> 
        <xsl:apply-templates select="@*|node()"/> 
       </xsl:element> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 
    <xsl:template match="@*"> 
     <xsl:attribute name="{name()}"> 
      <xsl:value-of select="."/> 
     </xsl:attribute> 
    </xsl:template> 
</xsl:stylesheet> 

輸出:

<x:getPosition xmlns:x="newPositionNS"> 
    <positionID> 
     <code>1</code> 
    </positionID> 
    <parameter>?</parameter> 
</x:getPosition> 

注意:如果你想要一個特定的前綴,你應該把它添加到的QName。如果你想刪除範圍的命名空間,你不應該在XSLT 1.0

+0

太棒了,謝謝Alejandro,我並不想強制命名空間前綴,'x'只是一個例子,但它可能是任何東西,這並不重要。重要的是子元素沒有名稱空間。 – Simon 2010-11-18 16:30:10

+0

@Luca:你很好。檢查我的評論,以你的淬火。也許你應該在Xalan報告一個錯誤。 – 2010-11-18 17:13:09

0

一,要做到這一點,而無需使用參數的變換使用xsl:copy是非常短的,簡單的

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:pos="positionNS" xmlns:x="newPositionNS" > 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="pos:getPositionRouter"> 
    <xsl:element name="x:getPosition"> 
    <xsl:apply-templates/> 
    </xsl:element> 
</xsl:template> 

<xsl:template match="*"> 
    <xsl:element name="{name()}"> 
    <xsl:copy-of select="namespace::*[not(name()='pos')]"/> 
    <xsl:apply-templates select="node()|@*"/> 
    </xsl:element> 
    <xsl:apply-templates/> 
</xsl:template> 
</xsl:stylesheet> 

應用時所提供的XML文檔

<pos:getPositionRouter xmlns:pos="positionNS"> 
    <positionID> 
     <code>1</code> 
    </positionID> 
    <parameter>?</parameter> 
</pos:getPositionRouter> 

想要的,正確的結果產生

<x:getPosition xmlns:x="newPositionNS"> 
    <positionID> 
     <code>1</code>1 
    </positionID> 
    <code>1</code>1 
    <parameter>?</parameter>? 
</x:getPosition> 

二, 參數化改造只是一點點複雜

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:param name="pOldNamespace" select="'positionNS'"/> 
<xsl:param name="pOldElementLocalname" select="'getPositionRouter'"/> 
<xsl:param name="pNewNamespace" select="'newPositionNS'"/> 
<xsl:param name="pNewElementLocalname" select="'getPosition'"/> 
<xsl:param name="pNewElementPrefix" select="'x'"/> 

<xsl:template match="*"> 
    <xsl:variable name="vReplacing" select= 
    "local-name()=$pOldElementLocalname 
    and 
    namespace-uri()=$pOldNamespace"/> 

    <xsl:variable name="vName"> 
    <xsl:choose> 
    <xsl:when test="$vReplacing"> 
    <xsl:value-of select="concat($pNewElementPrefix, ':', local-name())"/> 
    </xsl:when> 
    <xsl:otherwise><xsl:value-of select="name()"/></xsl:otherwise> 
    </xsl:choose> 
    </xsl:variable> 

    <xsl:variable name="vNamespace"> 
    <xsl:choose> 
    <xsl:when test="$vReplacing"> 
    <xsl:value-of select="$pNewNamespace"/> 
    </xsl:when> 
    <xsl:otherwise> 
    <xsl:value-of select="namespace-uri()"/> 
    </xsl:otherwise> 
    </xsl:choose> 
    </xsl:variable> 

    <xsl:element name="{$vName}" namespace="{$vNamespace}"> 
    <xsl:copy-of select="namespace::*[not(.=$pOldNamespace)]"/> 
    <xsl:apply-templates select="node()|@*"/> 
    </xsl:element> 
</xsl:template> 
</xsl:stylesheet> 
+0

@Dimitre:除了這個參數化是一個請求,並且只對一個特定的範圍內命名空間進行條帶化的好方法,我認爲你應該重新檢查你的樣式表:應用於沒有屬性規則的屬性和一個' 「任何元素」規則中的錯字。 – 2010-11-18 17:18:41

+0

@Alejandro:我很清楚我錯過了屬性 - 故意地,因爲源XML中沒有屬性。至於參數化 - 它只能在所提供的代碼中看到,我根本沒有讀到它......我不確定參數化是否是一項要求。 – 2010-11-18 18:10:32

+0

+1我喜歡名稱和名稱空間的變量聲明,使樣式表更具可讀性。 – 2010-11-18 19:16:29