首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >XSLT:递归合并同名节点

XSLT:递归合并同名节点
EN

Stack Overflow用户
提问于 2015-06-29 22:44:32
回答 1查看 734关注 0票数 3

虽然有很多类似标题的问题,但我找不到具体问题的答案。

假设我有一个xml树:

代码语言:javascript
复制
<input>
    <a>
        <b>
            <p1/>
        </b>
    </a>
    <a>
        <b>
            <p2/>
        </b>
    </a>
</input>

我想把这个当成

代码语言:javascript
复制
<input>
    <a>
        <b>
            <p1/>
            <p2/>
        </b>
    </a>
</input>

这种转换背后的想法是将一棵树,其中一个节点可以有多个同名的子节点,转换成一个更“格式良好”的树,其中每个节点只能有一个同名的子节点。(c.f.文件系统)。

我试着使用xslt-2的分组特性,但无法使递归工作。

代码语言:javascript
复制
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
  <xsl:strip-space elements="*"/>
    <xsl:template match="/">
        <output>
            <xsl:apply-templates select="*"/>
        </output>
    </xsl:template>

  <!-- this merges the children -->
  <xsl:template name="merge" match="*">

      <xsl:for-each-group select="child::*" group-by="local-name()">
          <xsl:variable name="x" select="current-grouping-key()"/>
          <xsl:element name="{$x}">
              <xsl:copy-of select="current-group()/@*"/>
              <xsl:apply-templates select="current-group()"/>
              <xsl:copy-of select="text()"/>
          </xsl:element>
      </xsl:for-each-group>
  </xsl:template>
</xsl:stylesheet>

我发现问题在于,我要为current-group()中的每个节点分别应用模板,但我不知道如何首先“加入”这个集合并整体应用该模板。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-07-01 09:08:56

我认为您可以使用分组来设置一个函数,请参阅http://xsltransform.net/bdxtqM/1,它确实

代码语言:javascript
复制
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
  xmlns:mf="http://example.com/mf"
  exclude-result-prefixes="mf">

  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
  <xsl:strip-space elements="*"/>

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

  <xsl:function name="mf:merge" as="node()*">
    <xsl:param name="elements" as="element()*"/>
    <xsl:for-each-group select="$elements" group-by="node-name(.)">
        <xsl:copy>
            <xsl:copy-of select="current-group()/@*"/>
            <xsl:sequence select="mf:merge(current-group()/*)"/>
        </xsl:copy>
    </xsl:for-each-group>
  </xsl:function>

  <xsl:template match="/*">
    <xsl:copy>
      <xsl:sequence select="mf:merge(*)"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31126808

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档