2009-12-04 102 views
12

好吧,我已經看到了這個問題上的許多變化,但沒有一個完全回答我試圖解決的問題,我太密集,不知道如何將其他答案應用於我正在嘗試做的事情。如何消除由一個XML文檔的XSLT轉換生成的xmlns =「」條目到另一個XML文檔

我有一些XML,看起來像下面這樣:

<?xml version="1.0" encoding="utf-8"?> 
<message> 
    <cmd id="api_info"> 
    <api-version>1.0</api-version> 
    <api-build>1.0.0.0</api-build> 
    </cmd> 
</message> 

現在我有一個XSLT轉換是我申請這個XML。該XSLT是類似以下內容:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       xmlns:fo="http://www.w3.org/1999/XSL/Format" 
       xmlns:xs="http://www.w3.org/2001/XMLSchema" 
       xmlns:fn="http://www.w3.org/2005/xpath-functions" 
       version="2.0"> 

    <xsl:output method="xml" version="1.0" indent="yes"/> 

    <xsl:template match="/"> 
     <xsl:apply-templates select="message"/> 
    </xsl:template> 

    <xsl:template match="message"> 
     <xsl:element name="message" xmlns="http://www.companyname.com/schemas/product/Version001"> 
      <xsl:apply-templates select="/message/cmd/@id"/> 
     </xsl:element> 
    </xsl:template> 

    <xsl:template match="/message/cmd/@id"> 
     <xsl:variable name="_commandType" select="/message/cmd/@id"/> 
     <xsl:element name="messageHeader"> 
      <xsl:element name="cmdType"> 
       <xsl:value-of select="$_commandType"/> 
      </xsl:element> 
     </xsl:element> 

     <xsl:element name="messageBody"> 
      <xsl:choose> 
       <xsl:when test="$_commandType = 'api_info'"> 
        <xsl:element name="apiInfoBody"> 
         <xsl:element name="apiVersion"> 
          <xsl:value-of select="/message/cmd/api-version"/> 
         </xsl:element> 
         <xsl:element name="apiBuild"> 
          <xsl:value-of select="/message/cmd/api-build"/> 
         </xsl:element> 
        </xsl:element> 
       </xsl:when> 
       <xsl:when test="$_commandType = 'communicationError'"> 
        <xsl:element name="communicationErrorBody"> 
         <xsl:element name="errorCode"> 
          <xsl:value-of select="error-code"/> 
         </xsl:element> 
         <xsl:element name="badCmd"> 
          <xsl:value-of select="bad-cmd"/> 
         </xsl:element> 
        </xsl:element> 
       </xsl:when> 
      </xsl:choose> 
     </xsl:element> 
    </xsl:template> 
</xsl:stylesheet> 

我得到的輸出基本上是我想要的,如下所示:

<?xml version="1.0" encoding="UTF-8"?> 
<message xmlns="http://www.companyname.com/schemas/product/Version001"> 
    <messageHeader xmlns=""> 
     <cmdType>api_info</cmdType> 
    </messageHeader> 
    <messageBody xmlns=""> 
     <apiInfoBody> 
      <apiVersion>1.0</apiVersion> 
      <apiBuild>1.0.0.0</apiBuild> 
     </apiInfoBody> 
    </messageBody> 
</message> 

但我不希望是的xmlns =」 「屬性<messageHeader> and <messageBody> elements。

現在我發現如果我明確指定XSLT中的名稱空間用於這些元素,那麼不需要的屬性會被下拉一個級別給這些屬性的子級。

我只能通過我的整個XSLT和明確屬性添加的xmlns =「」 http://www.companyname.com/schemas/product/Version001給我的每一個的xsl:元素定義,但我知道必須有一個更優雅的方式,我們的程序員如果我的XSLT不像簡單的例子那樣簡單,我就會想這樣做,但我知道必須有更好的方法。

有誰知道我在這裏失蹤?

謝謝,

AlarmTripper

回答

8

使用排除對結果的前綴在xsl:前綴爲「#默認」

在W3C這個基準是HERE

編輯樣式表標籤:OK,我應該有仔細研究了你的XSL。將消息標記上的xmlns移至樣式表標記。這會將所有結果元素放在同一個名稱空間中,並在消息標記中生成一個名稱空間屬性。我在Oxygen/XML中運行它並獲得了你想要的輸出。

+0

未更改輸出XML。 – AlarmTripper 2009-12-04 03:41:03

+0

您正在使用哪種XSLT處理器? – 2009-12-04 04:21:07

+0

是的,我確認你的新建議可以正常工作,並且可能是比我更好的解決方案,因爲它會將xmlns分配保留在樣式表元素中。而#default選項使我不必排除每個其他名稱空間前綴。 非常感謝。我對這個XSLT的東西有很多瞭解,我認爲命名空間可能是其中一個棘手的方面。 – AlarmTripper 2009-12-04 04:48:35

0

好吧,我想通了。

我想要的XSLT看起來是這樣的:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="2.0" 
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       xmlns:fo="http://www.w3.org/1999/XSL/Format" 
       xmlns:xs="http://www.w3.org/2001/XMLSchema" 
       xmlns:fn="http://www.w3.org/2005/xpath-functions" 
       exclude-result-prefixes="xsl fo xs fn"> 

    <xsl:output method="xml" version="1.0" indent="yes"/> 

    <xsl:template match="/"> 
     <xsl:apply-templates select="message"/> 
    </xsl:template> 

    <xsl:template match="message"> 
     <message namespace="http://www.companyname.com/schemas/product/Version001"> 
      <xsl:apply-templates select="/message/cmd/@id"/> 
     </message> 
    </xsl:template> 

    <xsl:template match="/message/cmd/@id"> 
     <xsl:variable name="_commandType" select="/message/cmd/@id"/> 

     <xsl:element name="messageHeader"> 
      <xsl:element name="cmdType"> 
       <xsl:value-of select="$_commandType"/> 
      </xsl:element> 
     </xsl:element> 

     <xsl:element name="messageBody"> 
      <xsl:choose> 
       <xsl:when test="$_commandType = 'api_info'"> 
        <xsl:element name="apiInfoBody"> 
         <xsl:element name="apiVersion"> 
          <xsl:value-of select="/message/cmd/api-version"/> 
         </xsl:element> 
         <xsl:element name="apiBuild"> 
          <xsl:value-of select="/message/cmd/api-build"/> 
         </xsl:element> 
        </xsl:element> 
       </xsl:when> 
       <xsl:when test="$_commandType = 'communicationError'"> 
        <xsl:element name="communicationErrorBody"> 
         <xsl:element name="errorCode"> 
          <xsl:value-of select="error-code"/> 
         </xsl:element> 
         <xsl:element name="badCmd"> 
          <xsl:value-of select="bad-cmd"/> 
         </xsl:element> 
        </xsl:element> 
       </xsl:when> 
      </xsl:choose> 
     </xsl:element> 
    </xsl:template> 
</xsl:stylesheet> 

是固定它是屬性添加排除對結果的前綴< XSL的變化:樣式>元素,以改變部分那是:

<xsl:template match="message"> 
     <xsl:element name="message" xmlns="http://www.companyname.com/schemas/product/Version001"> 
      <xsl:apply-templates select="/message/cmd/@id"/> 
     </xsl:element> 
    </xsl:template> 

是不是以下內容:

<xsl:template match="message"> 
     <message namespace="http://www.companyname.com/schemas/product/Version001"> 
      <xsl:apply-templates select="/message/cmd/@id"/> 
     </message> 
    </xsl:template> 

現在我又開心了。

有可能有更好的方法來做到這一點,但這對我很有用。任何未來的建議仍然受歡迎。

0

吉姆加里森的(更新)答案是所有你應該需要的。但是,您發佈的更新後的樣式表在結果中輸出了「命名空間」屬性,所以我不確定你有什麼好處。

要了解的關鍵是默認命名空間是如何工作的。不要將xmlns視爲可輸出到結果的屬性。相反,將其視爲樣式表的詞彙細節,其目的是爲它下面的所有元素(元素本身及其每個後代直到被覆蓋)設置默認名稱空間。 (反過來,它在結果XML中具有相同的功能,它與樣式表本身具有相同的功能)。

樣式表中的文字結果元素(例如,<消息>)以及< xsl:element >指令(例如,< xsl:element name =「message」>)在提供的名稱不使用前綴時都採用默認名稱空間。正如Jim Garrison所建議的,如果你想讓的所有都採用同一個命名空間,那麼你需要在樣式表頂部放置一個默認命名空間。否則,最終會得到一些不在該名稱空間中的元素,這就是爲什麼結果包含xmlns =「」(取消設置這些元素的名稱空間)的原因。

+0

謝謝Evan!我感謝我能夠到達的所有幫助。我讀過'xmlns'看起來像一個attrib,但事實並非如此。我確實回去修改了代碼,以便與Jim的建議相匹配,並添加了名稱空間限定符(術語?),以便我的名稱空間標記現在位於「樣式表」定義中,並且看起來像'xmlns:grf =「http: //www.blahblah。然後回過頭來確認我的元素前綴爲「grf:」 在這裏的專家的幫助是非常寶貴的,因爲我公司的其他人對XSLT或XPATH做了很多工作,我真的很享受它的學習! – AlarmTripper 2009-12-08 07:02:55