2013-10-14 61 views
0

我是新來的XSLT轉換和這裏就是我一直試圖做的一切晚上,我希望能得到您的幫助: 我有一個XML結構是這樣的:XSLT轉換元素的內容,而孩子們的屬性

<DEV> 
     <HDR> 
      <ApID>value1</ApID> 
      <STAT>value2</STAT> 
     </HDR> 
     <DSC> 
      <Cap>value3</Cap> 
     </DSC> 
    </DEV> 

基本上我需要沒有孩子的名字「V」翻譯元素的所有值到屬性:

<DEV> 
    <HDR> 
     <ApID V= "value1" /> 
     <STAT V= "value2" /> 
    </HDR> 
    <DSC> 
     <Cap V = "value3" /> 
    </DSC> 
</DEV> 

有什麼辦法來寫這樣的與XSLT通用的轉型?

回答

1

答案是肯定的!首先,您將基於您的XSLT XSLT identity transform。通過使用它,您只需要編寫模板來匹配您想要轉換的節點。這個模板可以自動將所有節點複製到您的XML中的屬性中。就你而言,你說你想匹配沒有孩子的元素(儘管嚴格來說,元素確實有孩子,他們有文本節點作爲孩子!但我想你的意思是他們沒有其他孩子元素)。所以,你的模板匹配會看這本

<xsl:template match="*[not(*)]"> 

哪裏*是用來匹配的元素符號。

然後,這個模板中,你可以複製的元素,並把文成使用XSL屬性:屬性

 <xsl:attribute name="V"> 
     <xsl:value-of select="text()" /> 
    </xsl:attribute> 

試試這個XSLT

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

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

    <xsl:template match="*[not(*)]"> 
     <xsl:copy> 
     <xsl:attribute name="V"> 
      <xsl:value-of select="text()" /> 
     </xsl:attribute> 
     <xsl:apply-templates select="@*" /> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

當適用於您的XML,以下是輸出

<DEV> 
    <HDR> 
    <ApID V="value1" /> 
    <STAT V="value2" /> 
    </HDR> 
    <DSC> 
    <Cap V="value3" /> 
    </DSC> 
</DEV> 
+0

這裏沒有模板規則問題的順​​序嗎?我的意思是在完成'match =「@ * | node()」'之後繼續處理? –

+1

XSLT具有模板優先級的概念。在兩個模板可以匹配同一個節點的情況下,它將優先考慮更具體的模板(即具有此處的條件的模板)。如果你願意,你可以在http://www.w3.org/TR/xslt#conflict閱讀它。 –

1

XSL T讓你遞歸遍歷節點樹。在遍歷樹時,可以通過創建比其他模板規則更具體的模板規則來獲得XSLT來處理節點。

你試圖解決的問題是在轉換你的XML樹時有一些細微的差別。良好的開端是採取identity transform

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="@*|node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

這個身份轉換隻會產生XML輸出相同的輸入XML。它按原樣匹配並複製每個XML節點。然後,您會逐步模擬您的輸出,直到您得到您想要的。請參閱<xsl:copy/>的文檔。

您想要進行復制的例外是當您遇到沒有任何子節點的元素時。要匹配任何元素,我們使用*。要匹配沒有元素,我們使用not(*)。爲了匹配沒有元素的元素,我們使用*[not(*)]。實際上,這些規則是由XSLT使用的查詢語言XPath定義的。讓我們來試試下面的XSLT對你的XML:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="1.0"> 
    <xsl:template match="*[not(*)]"> 
     <found-an-element-with-no-children/> 
    </xsl:template> 
    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

我們得到:

<?xml version="1.0" encoding="utf-8"?><DEV> 
    <HDR> 
     <found-an-element-with-no-children/> 
     <found-an-element-with-no-children/> 
    </HDR> 
    <DSC> 
     <found-an-element-with-no-children/> 
    </DSC> 
</DEV> 

的好處是,任何一個節點只能比對,在一次一個模板規則。我們更接近我們現在想要的地方。

這裏是<xsl:copy/>進來。我們現在將使用它,因爲我們想複製原始元素的名稱。

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="1.0"> 
    <xsl:template match="*[not(*)]"> 
     <xsl:copy> 
      <found-an-element-with-no-children/> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

現在,我們得到:

<?xml version="1.0" encoding="utf-8"?><DEV> 
    <HDR> 
     <ApID><found-an-element-with-no-children/></ApID> 
     <STAT><found-an-element-with-no-children/></STAT> 
    </HDR> 
    <DSC> 
     <Cap><found-an-element-with-no-children/></Cap> 
    </DSC> 
</DEV 

現在添加屬性到我們新創建的節點,並在其中包括我們剛纔匹配節點的文本內容:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="1.0"> 
    <xsl:template match="*[not(*)]"> 
     <xsl:copy> 
      <xsl:attribute name="V"> 
       <xsl:value-of select="."/> 
      </xsl:attribute> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

看起來我們在這裏:

<?xml version="1.0" encoding="utf-8"?><DEV> 
    <HDR> 
     <ApID V="value1"/> 
     <STAT V="value2"/> 
    </HDR> 
    <DSC> 
     <Cap V="value3"/> 
    </DSC> 
</DEV> 

現在兩個指針:

  1. ApIDSTATCap將能夠複製舊屬性無。您需要包含<xsl:apply-templates select="@*"/>以包含這些屬性。
  2. 而當您包含這些屬性時,如果原始輸入包含V屬性會發生什麼情況?
  3. 您可能想額外考慮當匹配的標籤沒有文字時會發生什麼 - 以及爲什麼。