2013-03-05 78 views
0

我有XSLT的背景很差,我需要轉換XML,看起來像這樣:選擇獨特屬性組

<row attribute1="1" attribute2="something" attribute3="somevalue"> 
<row attribute1="1" attribute2="something" attribute3="somevalue"> 
<row attribute1="2" attribute2="anotherthing" attribute3="somevalue"> 

的東西,看起來像這樣:

<row attribute1="1"> 
<row attribute1="2"> 

的改造任務有兩個更多的要求。我想獲得相同的結果如上述,但我想變更屬性的名稱,例如:

<row new_name_for_attribute1="1"> 
<row new_name_for_attribute1="2"> 

最後要求是,該方法可以適用於單一的屬性(如先前實例中),它們的子集(屬性1和屬性3)或行元素的所有屬性

在此先感謝。

回答

1

您可以輕鬆地轉換XML。這裏有一些你可以學習和學習一些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" indent="yes" /> 
    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 

    <!-- drop a row that matches a previous row of the same id --> 
    <xsl:template match="row[ preceding-sibling::row/@attribute1 = @attribute1 ]" /> 

    <!-- do stuff with the row. this template is equivalent to the default template copy. --> 
    <xsl:template match="row"> 
     <xsl:copy> 
     <xsl:apply-templates select="@*|node()" /> 
     </xsl:copy> 
    </xsl:template> 

    <!-- drop attribute2 attributes --> 
    <xsl:template match="@attribute2" /> 

    <!-- rename attribute1 --> 
    <xsl:template match="@attribute1"> 
     <xsl:attribute name="new_name_for_attribute1"> 
     <xsl:value-of select="."/> 
     </xsl:attribute> 
    </xsl:template> 
</xsl:stylesheet> 

使用此輸入:

<table> 
    <row attribute1="1" attribute2="something" attribute3="somevalue"> 
     <p>foo</p> 
    </row> 
    <row attribute1="1" attribute2="something" attribute3="somevalue"> 
     <p>bar</p> 
    </row> 
    <row attribute1="2" attribute2="anotherthing" attribute3="somevalue"> 
     <p>bazinga</p> 
    </row> 
</table> 

獲取你這樣的輸出:

<table> 
    <row new_name_for_attribute1="1" attribute3="somevalue"> 
     <p>foo</p> 
    </row> 
    <row new_name_for_attribute1="2" attribute3="somevalue"> 
     <p>bazinga</p> 
    </row> 
</table> 
+0

非常感謝,它的工作。如果我想過濾多個屬性,我應該將它們添加到'之前的兄弟姐妹'表達式中? – sblandin 2013-03-05 10:49:54

+0

對。如果您想按不同的屬性1和屬性3對進行過濾,那麼應該是 row [prior-sibling :: row/\ @ attribute1 = \ @ attribute1 and preceding-sibling :: row/\ @ attribute3 = \ @ attribute3] – ljdelight 2013-03-05 11:54:21

+0

(忽略反斜槓...所以抱怨說,我試圖通知太多的用戶) – ljdelight 2013-03-05 11:55:01

2

如果你是熱衷於瞭解XSLT的複雜性,你可能有興趣知道的一種叫做Muenchian Grouping的技術可以用來解決你的問題。要獲得不同的行,可以通過attribute1將它們有效地分組,然後爲每個組選擇組中的第一個元素。 (或丟棄不是第一個的元素)。 Muenchian分組是在XSLT 1.0中實現這一點的最有效方式。

在這種情況下,你開始通過定義鍵表示你的團隊,而你的情況是元素,通過ATTRIBUTE1

<xsl:key name="row" match="row" use="@attribute1" /> 

分組然後,如果您想選擇不同元素,你會選擇行最先發生在鍵對他們給予ATTRIBUTE1元素

<xsl:apply-templates select="row[generate-id() = generate-id(key('row', @attribute1)[1])]" /> 

或者,您可以有一個模板來忽略重複的元素(即,È哪些不是第一組中)

<xsl:template match="row[generate-id() != generate-id(key('row', @attribute1)[1])]" /> 

嘗試此XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 
    <xsl:key name="row" match="row" use="@attribute1" /> 

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

    <xsl:template match="row[generate-id() != generate-id(key('row', @attribute1)[1])]" /> 
</xsl:stylesheet> 

當施加到下面的XML

<rows> 
    <row attribute1="1" attribute2="something" attribute3="somevalue" /> 
    <row attribute1="1" attribute2="something" attribute3="somevalue" /> 
    <row attribute1="2" attribute2="anotherthing" attribute3="somevalue" /> 
</rows> 

以下是輸出

<rows> 
    <row attribute1="1" attribute2="something" attribute3="somevalue"></row> 
    <row attribute1="2" attribute2="anotherthing" attribute3="somevalue"></row> 
</rows> 

XSLT很容易就可以傾向於重新命名屬性或將其排除,如ljdelight的回答中所述。此外,如果你想在您的測試第二個屬性,你可以擴展你的關鍵,像這樣:

<xsl:key name="row" match="row" use="concat(@attribute1, '|', @attribute3)" /> 

,並忽略重複,模板會看這本

<xsl:template match="row 
    [generate-id() != generate-id(key('row', concat(@attribute1, '|', @attribute3))[1])]" /> 

唯一這裏需要注意的是使用管道字符|作爲分隔符。如果需要,這可以是任何其他字符,只要它不出現在屬性值中即可。

+0

好主意! +1我從來沒有想過與Muenchian組合使用連接 – ljdelight 2013-03-05 22:59:17

+0

坦克對於這個建議。當我回到我的xslt活動時,我也會嘗試這個:-) – sblandin 2013-03-06 16:01:11