2017-06-18 236 views
0

我需要通過基於屬性值的xslt合併兩個複雜元素節點,即例如當id = 1時,需要合併其相應的名稱值元素。等爲ID = 2,3 ...等xml通過xslt合併複雜節點

<?xml version="1.0" encoding="UTF-8"?> 
<xrefStore> 
<xrefData> 
    <entityData> 
     <entry id="1"> 
      <keyValue name="A" value=" "/> 
      <keyValue name="B" value=" "/> 
      <keyValue name="C" value=" "/> 
     </entry> 
     <entry id="2"> 
      <keyValue name="A" value=" "/> 
      <keyValue name="B" value=" "/> 
      <keyValue name="c" value=" "/> 
      <keyValue name="D" value=" "/> 
      <keyValue name="E" value=" "/> 
     </entry> 
     <entry id="1"> 
      <keyValue name="D" value=" "/> 
      <keyValue name="E" value=" "/> 
     </entry> 
    </xrefStore> 
</xrefData> 

的最終輸出應是如下,

<?xml version="1.0"?> 
<root> 
<set id="1"> 
    <nameValuePair> 
     <name>A</name> 
     <value> </value> 
    </nameValuePair> 
    <nameValuePair> 
     <name>B</name> 
     <value> </value> 
    </nameValuePair> 
    <nameValuePair> 
     <name>C</name> 
     <value> </value> 
    </nameValuePair> 
    <nameValuePair> 
     <name>D</name> 
     <value> </value> 
    </nameValuePair> 
    <nameValuePair> 
     <name>E</name> 
     <value> </value> 
    </nameValuePair> 
</set> 
<set id="2"> 
    <nameValuePair> 
     <name>A</name> 
     <value> </value> 
    </nameValuePair> 
    <nameValuePair> 
     <name>B</name> 
     <value> </value> 
    </nameValuePair> 
    <nameValuePair> 
     <name>C</name> 
     <value> </value> 
    </nameValuePair> 
    <nameValuePair> 
     <name>D</name> 
     <value> </value> 
    </nameValuePair> 
    <nameValuePair> 
     <name>E</name> 
     <value> </value> 
    </nameValuePair> 
</set> 
</root> 

我已經嘗試下面的代碼,但它不基於合併在身份證上。

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="/"> 
    <root> 
     <xsl:for-each select="xrefStore/xrefData/entityData/entity/entry"> 
      <set > 
       <xsl:attribute name="id"> 
        <xsl:value-of select="current()/@id" /> 
       </xsl:attribute> 
       <xsl:for-each select="current()/keyValue"> 
        <nameValuePair> 
         <name> 
          <xsl:value-of select="current()/@name" /> 
         </name> 
         <value> 
          <xsl:value-of select="current()/@value" /> 
         </value> 
        </nameValuePair> 
       </xsl:for-each> 
      </set> 
     </xsl:for-each> 
    </root> 
    </xsl:template> 
</xsl:stylesheet> 

任何形式的幫助表示讚賞。

我發現了相似的答案在這裏, Merge XML nodes using XSLT

,但我不明白他們執行的概念。

+0

的例子是混亂:哪裏的'1'在''來自?無論如何,這看起來像是一個分組問題,所以知道您是否可以使用XSLT 2.0至關重要。 –

+0

它是一個錯字Micheal,沒有價值1 ..它只是一個空值。這個分組可以使用版本2 xslt完成嗎? –

+0

它可以在XSLT 1.0和XSLT 2.0中完成 - 但方法不同。 - 請更正您的示例並澄清合併具有不同值的兩個節點時應該發生的情況。 –

回答

1

雖然這個問題是幾個月大,想過發佈一個答案,以便它可能會有用的其他人可能碰巧在這個問題上着陸。

XSLT 1.0解

甲鍵需要被聲明,這將被用於相同的節點的分組。在示例中,分組需要在<entry>元素的id屬性上完成。所有<entry>節點,其唯一標識符(由generate-id()函數返回)匹配的密鑰的唯一標識符做

<xsl:key name="kId" match="entry" use="@id" /> 

循環的需要。

<xsl:for-each select="entry[generate-id() = generate-id(key('kId', @id)[1])]"> 

通過組合鍵中的所有節點<keyValue>循環最後得到期望的結果。

<xsl:for-each select="key('kId',@id)/keyValue"> 

使用的版本1.0完整的XSL是如下。

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

    <!-- declare key to group nodes --> 
    <xsl:key name="kId" match="entry" use="@id" /> 

    <xsl:template match="entityData"> 
     <root> 
      <!-- loop through the grouped keys --> 
      <xsl:for-each select="entry[generate-id() = generate-id(key('kId', @id)[1])]"> 
       <set> 
        <xsl:attribute name="id"> 
         <xsl:value-of select="@id" /> 
        </xsl:attribute> 
        <!-- loop through the elements of the key --> 
        <xsl:for-each select="key('kId',@id)/keyValue"> 
         <nameValuePair> 
          <name> 
           <xsl:value-of select="@name" /> 
          </name> 
          <value> 
           <xsl:value-of select="@value" /> 
          </value> 
         </nameValuePair> 
        </xsl:for-each> 
       </set> 
      </xsl:for-each> 
     </root>  
    </xsl:template> 
</xsl:stylesheet> 

XSLT 2.0解決方案

2.0版提供了grouping使用<xsl:for-each-group>特徵的更簡單的方法。以下是XSL。

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes" /> 
    <xsl:strip-space elements="*"/> 

    <xsl:template match="entityData"> 
     <root> 
      <!-- loop through 'entry' groups grouped by 'id' attribute --> 
      <xsl:for-each-group select="entry" group-by="@id"> 
       <set> 
        <xsl:attribute name="id"> 
         <xsl:value-of select="current-grouping-key()" /> 
        </xsl:attribute> 
        <!-- loop through current group for all 'keyValue' elements --> 
        <xsl:for-each select="current-group()/keyValue"> 
         <nameValuePair> 
          <name> 
           <xsl:value-of select="@name" /> 
          </name> 
          <value> 
           <xsl:value-of select="@value" /> 
          </value> 
         </nameValuePair> 
        </xsl:for-each> 
       </set> 
      </xsl:for-each-group> 
     </root> 
    </xsl:template> 
</xsl:stylesheet> 

兩種溶液變換所述輸入XML成所需的輸出

<root> 
    <set id="1"> 
     <nameValuePair> 
     <name>A</name> 
     <value> </value> 
     </nameValuePair> 
     <nameValuePair> 
     <name>B</name> 
     <value> </value> 
     </nameValuePair> 
     <nameValuePair> 
     <name>C</name> 
     <value> </value> 
     </nameValuePair> 
     <nameValuePair> 
     <name>D</name> 
     <value> </value> 
     </nameValuePair> 
     <nameValuePair> 
     <name>E</name> 
     <value> </value> 
     </nameValuePair> 
    </set> 
    <set id="2"> 
     <nameValuePair> 
     <name>A</name> 
     <value> </value> 
     </nameValuePair> 
     <nameValuePair> 
     <name>B</name> 
     <value> </value> 
     </nameValuePair> 
     <nameValuePair> 
     <name>c</name> 
     <value> </value> 
     </nameValuePair> 
     <nameValuePair> 
     <name>D</name> 
     <value> </value> 
     </nameValuePair> 
     <nameValuePair> 
     <name>E</name> 
     <value> </value> 
     </nameValuePair> 
    </set> 
</root>