【问题标题】:xml complex nodes merging through xsltxml复杂节点通过xslt合并
【发布时间】:2017-06-18 06:19:37
【问题描述】:

我需要根据属性值通过 xslt 合并两个复杂元素节点,例如,当 id=1 时,需要合并其各自的名称值元素。以此类推,id=2, 3 ..etc

<?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>

我试过下面的代码,但它没有根据 id 合并。

<?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

但我不明白它们的实现概念。

【问题讨论】:

  • 这个例子令人困惑:&lt;value&gt;1&lt;/value&gt; 中的1 来自哪里?无论如何,这看起来像是一个分组问题,因此了解您是否可以使用 XSLT 2.0 非常重要。
  • 这是一个错字 Micheal,没有值 1.. 它只是一个空值。这种分组可以使用版本 2 xslt 来完成吗?
  • 它可以在 XSLT 1.0 和 XSLT 2.0 中完成 - 但方法不同。 -- 请更正您的示例并阐明合并具有不同值的两个节点时会发生什么。
  • 我不确定如何编辑内容以更正它,我试过了。至于预期的输出,对于每个条目,我需要对每个 keyValue 进行分组,并获得一个具有合并 keyValue 的 id 的唯一条目。
  • 不清楚。请举个例子。并说明您的处理器版本。

标签: xml xslt merge


【解决方案1】:

虽然这个问题已经有几个月的历史了,但还是想发布一个答案,以便对可能碰巧遇到这个问题的其他人有用。

XSLT 1.0 解决方案

需要声明一个用于对相同节点进行分组的键。在示例中,需要对&lt;entry&gt; 元素的id 属性进行分组。

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

需要对唯一标识符(由generate-id() 函数返回)与键的唯一标识符匹配的所有&lt;entry&gt; 节点进行循环。

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

最后循环遍历分组键中的所有&lt;keyValue&gt; 节点以获得所需的结果。

<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 版使用&lt;xsl:for-each-group&gt; 功能为grouping 提供了一种更简单的方法。下面是 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>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-03
    相关资源
    最近更新 更多