【问题标题】:How to merge xml nodes with common attribute value如何合并具有公共属性值的xml节点
【发布时间】:2018-09-18 07:24:47
【问题描述】:

我想获取一些 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,另一种使用其他语言。

【问题讨论】:

  • 您不能使用 XPath 修改 XML 源。您应该改为检查 XSLT。另请注意,不包含解决问题尝试的问题应以太宽泛偏离主题而关闭
  • 这是一个分组问题。如果您使用的是 XSLT 1.0,请继续阅读 Muenchian Grouping。如果您可以使用 XSLT 2.0 或更高版本,那么xsl:for-each-group 将成为您的朋友。如果您无法使其正常工作,请发布您尝试过的内容,我相信您会得到答案。谢谢!

标签: xml xslt xpath data-conversion


【解决方案1】:

你可以试试这个:

<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查看转换

【讨论】:

    【解决方案2】:
    <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.
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-27
      • 1970-01-01
      • 1970-01-01
      • 2019-05-29
      • 2011-10-05
      相关资源
      最近更新 更多