首页 > 解决方案 > 如何使用 XSLT 版本 1 对附近的相同元素进行分组

问题描述

我需要通过使用 XSLT 版本 1 对附近的元素进行分组来将 XML 结构转换为另一个 XML 结构,并将其存储到一个变量中以供以后处理。

我目前的解决方案: https ://xsltfiddle.liberty-development.net/naZXVF1/3

XML

<?xml version="1.0"?>
 <Items>
      <Parameter>1</Parameter>
      <Parameter>2</Parameter>
      <Menu>1</Menu>
      <Parameter>3</Parameter>
      <Parameter>4</Parameter>
      <Menu>2</Menu>
      <Menu>3</Menu>
      <Parameter>5</Parameter>
      <Parameter>6</Parameter>
      <Parameter>7</Parameter>
      <Parameter>8</Parameter>
  </Items>

预期结果

<Items>
   <Parameters>
      <Parameter>1</Parameter>
      <Parameter>2</Parameter>
   </Parameters>
   <Menus>
     <Menu>1</Menu>
   </Menus>  
   ...
</Items>

标签: xsltxslt-1.0xslt-grouping

解决方案


要么使用兄弟递归,要么使用复杂的键来识别属于一起的元素:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output indent="yes"/>

  <xsl:key name="group" match="*[name(preceding-sibling::*[1]) = name()]"
    use="generate-id(preceding-sibling::*[name() = name(current())][name(preceding-sibling::*[1]) != name()][1])"/>

  <xsl:template match="Items">
      <xsl:copy>
          <xsl:apply-templates select="*[name(preceding-sibling::*[1]) != name()]"/>
      </xsl:copy>
  </xsl:template>

  <xsl:template match="Items/*">
      <xsl:element name="{name()}s">
          <xsl:copy-of
            select=". | key('group', generate-id())"/>
      </xsl:element>
  </xsl:template>
</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/naZXVF1/4


推荐阅读