2011-07-04 166 views
3

提取XML文件的子集。當我輸入XML爲:刪除命名空間,並使用XSL

<country> 
     <state> 
      <city> 
       <name>DELHI</name>    
      </city> 
     </state> 
    </country> 

對於所需的輸出如下:

<city> 
    <name>DELHI</name>    
</city 

以下XSL是工作的罰款:

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

但是相同的XSL不適用於上面的輸入XML,如果名稱空間被添加: 象下面這樣:

<country xmlns="http://india.com/states" version="1.0"> 
    <state> 
     <city> 
      <name>DELHI</name>    
     </city> 
    </state> 
</country> 

我要與將要複製的城市元素一起被除去名字空間。

任何幫助,將不勝感激。 感謝

+0

問得好,+1。查看我的答案,獲得完整,簡短和簡單的解決方案。還提供了詳細的解釋。 –

+0

我更新了我的答案,修改了「另一個約翰」的問題。如果這是你,請聯繫SO合併你的兩個身份。 –

+0

我的回答對你有用嗎? –

回答

2

這是XPath的,XML和XSLT的最常見問題。搜索「默認命名空間和XPath表達式」。

作爲用於溶液

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:x="http://india.com/states"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:template match="*"> 
    <xsl:element name="{name()}"> 
    <xsl:copy-of select="@*"/> 
    <xsl:apply-templates/> 
    </xsl:element> 
</xsl:template> 


<xsl:template match="*[not(ancestor-or-self::x:city)]"> 
    <xsl:apply-templates/> 
</xsl:template> 
</xsl:stylesheet> 

當這個變換所提供的XML文檔施加:

<country xmlns="http://india.com/states" version="1.0"> 
    <state> 
     <city> 
      <name>DELHI</name> 
     </city> 
    </state> 
</country> 

有用結果產生

<city> 
    <name>DELHI</name> 
</city> 

說明

  1. 在XPath前綴的元素名稱是始終considerd是在 「沒有命名空間」。但是,所提供的XML文檔中的每個元素名稱都位於非空名稱空間(默認名稱空間"http://india.com/states")中。因此,//city沒有選擇任何節點(因爲XML文檔中沒有元素沒有名稱空間),而//x:city其中x:綁定到名稱空間"http://india.com/states"選擇所有城市元素(位於名稱空間"http://india.com/states"中)。

  2. 在這個轉換中有兩個模板。第一個模板匹配任何元素並重新創建它,但是在無名稱空間中。它還複製所有屬性,然後將模板應用於此元素的子節點。

  3. 第二個模板覆蓋了不是city元素的祖先的所有元素的第一個模板,或者它們自己不是city元素的第一個模板。此處的操作是在所有子節點上應用模板。

UPDATE:該OP已經修改了問題,問爲什麼在處理一個新的,修改後的XML文檔的結果不想要的文字:

<country xmlns="http://india.com/states" version="1.0"> 
     <state> 
      <city> 
       <name>DELHI</name> 
      </city> 
     </state> 
     <state2> 
      <city2> 
       <name2>MUMBAI</name2> 
      </city2> 
     </state2> 
</country> 

爲了到產生文本「MUMBAI」,上面的轉換需要稍微修改 - 忽略(不復制)任何沒有x:city祖先的文本節點。爲此,我們添加下面一行,空模板:

<xsl:template match="text()[not(ancestor::x:city)]"/> 

整個改造現在變成

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:x="http://india.com/states"> 
    <xsl:output omit-xml-declaration="yes" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:template match="*"> 
     <xsl:element name="{name()}"> 
     <xsl:copy-of select="@*"/> 
     <xsl:apply-templates/> 
     </xsl:element> 
    </xsl:template> 

    <xsl:template match="*[not(ancestor-or-self::x:city)]"> 
     <xsl:apply-templates/> 
    </xsl:template> 

    <xsl:template match="text()[not(ancestor::x:city)]"/> 
</xsl:stylesheet> 

,結果仍然是有用的,正確的一個

<city> 
    <name>DELHI</name> 
</city> 
0

你可以通過使用如下模板得到想要的輸出:

<xsl:template match="*[not(ancestor-or-self::x:*[starts-with(name(),'city')])]"> 
    <xsl:apply-templates/> 
</xsl:template> 

<xsl:template match="/"> 
    <xsl:apply-templates select="//x:*[starts-with(name(),'city')]"/> 
</xsl:template> 

微軟(R)XSLT處理器4.0版你的新的輸入進行了測試,得出:

<city> 
    <name>DELHI</name> 
</city> 
<city2> 
    <name2>MUMBAI</name2> 
</city2>