2017-02-14 121 views
0

我有這樣的XML:XSLT轉換(XML到XML)

<object> 
    <string name "order">1<string> 
    <string name "item">1<string> 
</object> 
<object> 
    <string name "order">1<string> 
    <string name "item">2<string> 
</object> 
<object> 
    <string name "order">2<string> 
    <string name "item">1<string> 
</object> 

我想將XML轉換到這個strukture:

<object order=1> 
    <string name "item">1<string> 
    <string name "item">2<string> 
</object> 
<object order=2> 
    <string name "item">1<string> 
</object> 

我想與動態轉換輸入XML XSLT,但我很難做到這一點。

+1

這是*分組*問題。做一個搜索 - 這可能是最經常被問到的XSLT問題。請注意,對於XSLT 1.0或2.0,答案是不同的。 –

回答

0

要做的第一件事就是將源XML轉換爲適當的形式。

  1. XML文檔包含只有一個根標籤(讓我們稱之爲) 和該標籤可以包含多個源代碼(例如,對象)。

  2. 每個標籤(如你在串寫標籤)可以包含屬性 (在你的情況爲了),但它們之間必須是「=」標誌。

  3. 對象標籤的情況下,你記得把在「/」關閉標籤, 但你在每個關標籤忘了。

所以正確的輸入XML(需要更正後)爲:

<main> 
    <object> 
    <string name="order">1</string> 
    <string name="item">1</string> 
    </object> 
    <object> 
    <string name="order">1</string> 
    <string name="item">2</string> 
    </object> 
    <object> 
    <string name="order">2</string> 
    <string name="item">1</string> 
    </object> 
</main> 

現在讓我們倒在主業。 在描述中我把行號 - 引用到最終的解決方案。

我們從xsl:輸出indent =「是」(第2行)開始,否則所有內容 將在單行(難以閱讀)中。

該XML代碼包含單個tempate匹配主要標記(第4行)。

它所做的第一件事是拷貝(開啓和關閉標籤 - 第5行)。

然後,第6行包含分組循環(,針對每個組)。細分電子郵件廣告是對象元素中的對象(參見選擇子句)和分組關鍵是子標籤的含量(相對於當前對象)與屬性名稱等於「命令」(見組 - 由子句)。

所以第一組包含對象標籤號1和2(它們都具有 字符串名稱=「順序」標籤用的「1」的內容和所述第二組包含 對象標籤號3。

然後(對於每組源對象標籤)

我們創建輸出對象元件(第7行),該元件必須具有一個ATT ribute命名爲order與當前分組鍵(第8行)的值爲 。

當前元素(輸出對象)是包含在 當前組從每個元素數據,所以我們必須寫的for-each語句,通過 所有源循環對象標籤 - 的含量(請參閱選擇子句,第9行)。

在此循環中,對於每個輸入對象,我們創建了一個字符串元素(第10行)。

這個元素有一個名爲「名」的屬性(見條款)和 其值應爲「項目」(見選擇條款) - 行11

的最後一件事要做的就是創建輸出標籤的內容 - 與 屬性的項目值 價值孩子標籤的(相對於當前對象) - 行12

XSL中的所有其他行都是結束標記。

下面有一個完整的XSL解決方案。

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

    <xsl:template match="main"> 
    <xsl:copy> 
     <xsl:for-each-group select="object" group-by="string[@name='order']"> 
     <xsl:element name="object"> 
      <xsl:attribute name="order" select="current-grouping-key()"/> 
      <xsl:for-each select="current-group()"> 
      <xsl:element name="string"> 
       <xsl:attribute name="name" select="'item'"/> 
       <xsl:value-of select="string[@name='item']"/> 
      </xsl:element> 
      </xsl:for-each> 
     </xsl:element> 
     </xsl:for-each-group> 
    </xsl:copy> 
    </xsl:template> 

</xsl:transform>