微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

xml – 在XSLT中递归组合相同的兄弟元素

如何使用XSLT将具有相同名称和相同属性的所有同级元素合并到单个元素中?转换也应递归地应用于正在合并的元素的子元素.这是源文件
<?xml version="1.0"?>
<Root>
  <Element id="UniqueId1">
    <SubElement1/>
    <SubElement2>
      <LeafElement1/>
    </SubElement2>
  </Element>
  <Element id="UniqueId1">
    <SubElement2>
      <LeafElement1/>
      <LeafElement2/>
    </SubElement2>
    <SubElement3/>
  </Element>
  <Element id="UniqueId2">
    <SubElement1/>
    <SubElement4/>
  </Element>    
</Root>

它应该转变为:

<?xml version="1.0"?>
<Root>
  <Element id="UniqueId1">
    <SubElement1/>
    <SubElement2>
      <LeafElement1/>
      <LeafElement2/>
    </SubElement2>
    <SubElement3/>
  </Element>
  <Element id="UniqueId2">
    <SubElement1/>
    <SubElement4/>
  </Element>    
</Root>

具有相同名称属性的任何元素都合并为一个元素.然后,他们的孩子接受检查.如果其中任何一个具有相同的名称和相同的属性,则将它们组合在一起.此转换以递归方式应用于所有元素.

编辑:为了澄清,所有这些条件必须为两个要合并的元素.

>它们具有相同的元素名称
>它们具有相同的属性
>每个相应属性的值都相同
>他们是兄弟姐妹(递归应用,因此在考虑孩子之前,任何相同的父元素都会被合并和组合)

这些元素是相同的,应该合并:

>< Item />和< Item /> (同名,相同属性)
>< Item Attr =“foo”/>和< Item Attr =“foo”/> (同名,相同属性)

这些元素不相同,不应合并:

>< Item />和< SubItem /> (不同的名字)
>< Item Attr =“foo”/>和< Item /> (不同的属性)
>< Item Attr =“foo”/>和< Item Attr =“bar”/> (不同的属性值)

这应该做的工作:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" version="1.0" indent="yes"/>
  <xsl:key name="atts-by-name" match="@*" use="name()"/>
  <xsl:template match="Root">
    <xsl:copy>
      <xsl:call-template name="merge">
        <xsl:with-param name="elements" select="*"/>
      </xsl:call-template>
    </xsl:copy>
  </xsl:template>
  <xsl:template name="merge">
    <xsl:param name="elements"/>
    <xsl:for-each select="$elements">
      <xsl:variable name="same-elements" select="$elements[name()=name(current()) and count(@*)=count(current()/@*) and count(@*[. = key('atts-by-name',name())[generate-id(..)=generate-id(current())]])=count(@*)]"/>
      <xsl:if test="generate-id($same-elements[1]) = generate-id()">
        <xsl:copy>
          <xsl:copy-of select="@*"/>
          <xsl:call-template name="merge">
            <xsl:with-param name="elements" select="$same-elements/*"/>
          </xsl:call-template>
        </xsl:copy>
      </xsl:if>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

棘手的部分是相同元素的定义;按名称索引属性对于验证所有属性的真实性是必需的.

原文地址:https://www.jb51.cc/xml/293043.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。