2017-06-18 156 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>