2013-02-28 84 views
2

我需要爲已命名空間的XML文件添加額外的命名空間,但僅限於特定元素不存在時。使用XSLT添加其他命名空間

我的XML文檔的樣子:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<everyone xmlns="AAA" xmlns:ns2="BBB" xmlns:ns3="CCC" company="TestingCorp"> 
    <common>Stuff Here</common> 
    <ns2:person id="123"> 
     <ns3:firstname>Billy</ns3:firstname> 
     <ns2:lastname>Bobby</ns2:lastname> 
    </ns2:person> 
</everyone> 

...如果沒有NS3:在人的要素名字元素,我想補充一個新的命名空間,(如的xmlns:青蛙= 「FFF」),也可以作爲如下所示的內人的附加元件:

所需的輸出:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<everyone xmlns="AAA" xmlns:ns2="BBB" xmlns:ns3="CCC" xmlns:frog="FFF" company="TestingCorp"> 
    <common>Stuff Here</common> 
    <ns2:person id="123"> 
     <frog:title> 
      <Master/> 
     </frog:title> 
     <ns2:lastname>Bobby</ns2:lastname> 
    </ns2:person> 
</everyone> 

我的XSL文檔目前是:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:output method="xml" encoding="UTF-8" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

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

    <xsl:template match="/*"> 
    <xsl:element name="ns:{local-name()}"> 
     <xsl:attribute name="frog">fff</xsl:attribute> 
     <xsl:apply-templates select="node()|@*" /> 
    </xsl:element> 
    </xsl:template> 

</xsl:stylesheet> 

....不幸的是這是行不通的。

我已經嘗試了很多不同的東西,但似乎無法使用XSLT v1.0來實現這一點。任何幫助將不勝感激。

回答

2

首先,你需要在你的樣式表申報各種命名空間,還有"AAA"默認命名空間

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns="AAA" 
    xmlns:frog="FFF" 
    xmlns:ns2="BBB" 
    xmlns:ns3="CCC"> 

    <xsl:output method="xml" encoding="UTF-8" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

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

    <!-- for a Person with no firstname, add a frog:title --> 
    <xsl:template match="ns2:person[not(ns3:firstname)]"> 
     <xsl:copy> 
      <!-- must handle attributes before elements/text nodes --> 
      <xsl:apply-templates select="@*" /> 
      <frog:title> 
       <Master/> 
      </frog:title> 
      <xsl:apply-templates select="node()" /> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

這將產生

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<everyone xmlns="AAA" xmlns:ns2="BBB" xmlns:ns3="CCC" company="TestingCorp"> 
    <common>Stuff Here</common> 
    <ns2:person id="123"> 
     <frog:title xmlns:frog="FFF"> 
      <Master/> 
     </frog:title> 
     <ns2:lastname>Bobby</ns2:lastname> 
    </ns2:person> 
</everyone> 

如果xmlns:frog絕對必須everyone元素而不是每個frog:title然後你可以添加另一個模板

<xsl:template match="/*"> 
    <xsl:copy> 
    <xsl:copy-of select="document('')/xsl:stylesheet/namespace::frog" /> 
    <xsl:apply-templates select="@*|node()" /> 
    </xsl:copy> 
</xsl:template> 

將樣式表元素中的名稱空間聲明覆制掉(儘管這意味着每個輸出文檔都有一個xmlns:frog聲明,即使它不涉及任何frog:*元素)。


編輯:顯然Xalan的不會document('')喜歡copy-of命名空間,作爲一種替代,如果你知道文檔元素將始終具有相同的名稱,那麼你可以硬編碼,作爲一個文字結果元素

<xsl:template match="/*"> 
    <everyone xmlns:frog="FFF"> 
    <xsl:copy-of select="namespace::*" /> 
    <xsl:apply-templates select="@*|node()" /> 
    </everyone> 
</xsl:template> 

(技術上會做你想做的,即使沒有這個模板中明確xmlns:frog,因爲文字結果元素總是命名空間聲明在範圍上的點在樣式表他們一重新申明,但如果包含它,則意圖可以更清楚地說明)

This mailing list post對於document('')無法正常工作的原因提供了一些可能的見解。

+0

感謝您的快速響應。我還沒有測試這個,但是由於我對XSLT的知識非常有限,我不能看到這隻會添加到青蛙:title元素中,如果ns3:firstname元素從人員中缺失。 – user2119994 2013-02-28 15:43:16

+0

@ user2119994訣竅在'match =「ns2:person [not(ns3:firstname)]」 - 這個模板只適用於沒有'firstname'的'person'元素,那些有' firstname將使用身份模板來代替。 – 2013-02-28 15:44:38

+0

嗨,另外,有沒有什麼辦法通過指定我想添加到根元素的新命名空間並複製所有現有的命名空間,而不必指定所有其他的命名空間呢? – user2119994 2013-02-28 15:46:47