如何合并 xml 个具有公共属性值的节点

How to merge xml nodes with common attribute value

我想获取一些 XML 文档并合并某个级别上具有相同属性值的所有节点。例如,如果我有这种形式的文件,

<xml>
 <books id="X">
  <book name="Story"/>
  <book name="Tale"/>
 </books>
 <books id="X">
  <book name="Folklore"/>
  <book name="Magic"/>
 </books>
 <books id="Y">
  <book name="Harry Potter"/>
  <book name="LotR"/>
 </books>
</xml>

那么我希望能够将其转换为以下文档:

<xml>
 <books id="X">
  <book name="Story"/>
  <book name="Tale"/>
  <book name="Folklore"/>
  <book name="Magic"/>
 </books>
 <books id="Y">
  <book name="Harry Potter"/>
  <book name="LotR"/>
 </books>
</xml>

如果可能的话,我非常希望有多个解决方案。例如,一种使用 XSLT,另一种使用其他语言。

<xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="books[1][@id='X']">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
        <xsl:apply-templates/>
            <xsl:apply-templates select="following-sibling::books[@id='X']/book"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="books[@id='X' and preceding-sibling::books[@id='X']]"/>
    <xsl:template match="book">
        <xsl:copy>
        <xsl:apply-templates select="@*"/>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>
check it.

你可以试试这个:

<xsl:template match="xml">
        <xsl:for-each-group select="books" group-by="@id">
            <xsl:copy>
                <xsl:attribute name="id" select="current-grouping-key()"/>
                <xsl:apply-templates select="current-group()/*"/>
            </xsl:copy>
        </xsl:for-each-group>
    </xsl:template>

<xsl:template match="node() | @*">
    <xsl:copy>
        <xsl:apply-templates select="node() | @*"/>
    </xsl:copy>
</xsl:template>

https://xsltfiddle.liberty-development.net/gWmuiJR

查看转换