2011-07-07 151 views
2

我會使用XSLT轉換XSLT轉換

首先到第一個XML轉換成第二個:

<Data> 
<Time> 
    <ID>IDvalue1</ID> 
    <field1>PropertyValue1</field1> 
    <field2>PropertyName1</field2> 
</Time> 
<Time> 
    <ID>IDvalue2</ID> 
    <field1>PropertyValue2</field1> 
    <field2>PropertyName1</field2> 
</Time> 
<Time> 
    <ID>IDvalue1</ID> 
    <field1>PropertyValue3</field1> 
    <field2> PropertyName2</field2> 
</Time> 
<Time> 
    <ID>IDvalue2</ID> 
    <field1>PropertyValue4</field1> 
    <field2>PropertyName2</field2> 
</Time> 
</Data> 
.... 

二:

<Data> 
<Time> 
    <ID>IDvalue1</ID> 
    <PropertyName1>PropertyValue1</PropertyName1> 
    <PropertyName2>PropertyValue3</PropertyName2> 
</Time> 
<Time> 
    <ID>IDvalue2</ID> 
    <PropertyName1>PropertyValue2</ PropertyName1> 
    <PropertyName2>PropertyValue4</PropertyName2> 
</Time> 
</Data> 
..... 

在第一個XML那裏的數ID節點具有相同的值。在第二個XML中,它們被編譯成單個節點。在第一個XML中的每個ID後面都有field1和field2節點。在第二個XML中,必須創建新的節點,其中field2是標記名稱,field1是value。這些新節點是從具有相同值的所有ID節點收集的。

你能幫我寫XSLT代碼嗎?

+0

您可以在SO找到很多關於分組的問題/答案。但是,如果您是XSLT新手,分組可能很難理解並適用於您的用例。 +1爲你明確的問題。 –

回答

2

使用該模板:

<?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:key name="k" match="Time" use="ID"/> 

    <xsl:template match="Data"> 
    <Data> 
     <xsl:apply-templates select="Time[generate-id(.) = generate-id(key('k', ID))]"/> 
    </Data> 
    </xsl:template> 

    <xsl:template match="Time"> 
    <Time> 
     <xsl:copy-of select="ID"/> 
     <xsl:for-each select="key('k', ID)"> 
     <xsl:element name="{normalize-space(field2)}"> 
      <xsl:value-of select="field1"/> 
     </xsl:element> 
     </xsl:for-each> 
    </Time> 
    </xsl:template> 

</xsl:stylesheet> 

輸出:

<?xml version="1.0" encoding="utf-8"?> 
<Data> 
    <Time> 
    <ID>IDvalue1</ID> 
    <PropertyName1>PropertyValue1</PropertyName1> 
    <PropertyName2>PropertyValue3</PropertyName2> 
    </Time> 
    <Time> 
    <ID>IDvalue2</ID> 
    <PropertyName1>PropertyValue2</PropertyName1> 
    <PropertyName2>PropertyValue4</PropertyName2> 
    </Time> 
</Data> 
+0

謝謝,你的回答很有用。如何將標籤的名稱傳遞給XSLT轉換? (我的標籤並不總是像

+0

@ Egor4eg,你可以在XSLT中傳遞參數,但有一些限制。看看這個主題:http://stackoverflow.com/questions/4807377/how-can-you-pass-in-a-parameter-to-an-xslt-that-c​​an-be-used-in-a-xslkey –

2

這是一個標準的分組問題。如果您搜索「XSLT分組」,您會找到大量幫助。 polishchuk已經證明,使用xsl:for-each-group指令在XSLT 2.0中編組非常容易,但在XSLT 1.0中非常棘手。 (就我個人而言,如果不先知道您正在使用哪個版本的XSLT以及爲什麼 - 在兩種情況下代碼是如此不同),我甚至不會嘗試回答分組問題。)

+0

我是XSLT轉換中的新手。從未做過。我沒有嘗試polishchuk的答案。我打算在幾天內完成。 關於XSLT版本 - 我不確定。我正在使用ASP.NET 4.0。我應該使用哪個版本? – Egor4eg

1

Microsoft .NET Framework尚不支持XSLT 2.0 。但是,如果您要使用ASP .NET中的XSLT,您可以輕鬆實現(@Michael Key)Saxon。有關更多信息,請參閱this topic

準備就緒後,您的分組解決方案將非常簡單。這裏應用您的問題的XSLT 2.0分組示例:

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

    <xsl:template match="Data"> 
     <Data> 
      <xsl:for-each-group select="Time" group-by="ID"> 
       <Time> 
        <xsl:copy-of select="ID"/> 
        <xsl:apply-templates select="current-group()"/> 
       </Time> 
      </xsl:for-each-group> 
     </Data> 
    </xsl:template> 

    <xsl:template match="Time"> 
     <xsl:element name="{field2}"> 
      <xsl:value-of select="field1"/> 
     </xsl:element> 
    </xsl:template> 

</xsl:stylesheet> 
+0

非常感謝。該解決方案看起來比XSLT 1.0版更好。但是我不打算使用任何額外的代碼來處理2.0,因爲我沒有時間。所以,答案+1,我會用polishchuk的解決方案。 – Egor4eg