xml - 按 Xsl 中子项的值对 xml 节点进行分组

标签 xml xslt xpath

<root>
<element>
<id>1</id>
<group>first</group>
</element>

<element>
<id>2</id>
<group>second</group>
</element>


<element>
<id>3</id>
<group>first</group>
</element>
...
<root>

如何在 xslt 1.0 中按组名对元素进行分组。 输出:

<root>
<group name="first">
 <element>
    <id>1</id>
    <group>first</group>
 </element>
 <element>
    <id>3</id>
    <group>first</group>
 </element>
</group>
<group name="second">
 <element>
    <id>2</id>
    <group>second</group>
    </element>
</group>
</root>

有什么想法吗?

最佳答案

我。这是一个完整且非常简短的 XSLT 1.0 解决方案:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 
 <xsl:key name="kElsByGroup" match="element" use="group"/>
 
 <xsl:template match="/*">
  <root>
   <xsl:apply-templates/>
  </root>
 </xsl:template>

 <xsl:template match=
   "element[generate-id()=generate-id(key('kElsByGroup',group)[1])]">

  <group name="{group}">
   <xsl:copy-of select="key('kElsByGroup',group)"/>
  </group>
 </xsl:template>
 
 <xsl:template match=
   "element[not(generate-id()=generate-id(key('kElsByGroup',group)[1]))]"/>

</xsl:stylesheet>

当此转换应用于提供的 XML 文档时:

<root>
    <element>
        <id>1</id>
        <group>first</group>
    </element>
    <element>
        <id>2</id>
        <group>second</group>
    </element>
    <element>
        <id>3</id>
        <group>first</group>
    </element>
</root>

产生了想要的、正确的结果:

<root>
    <group name="first"><element>
        <id>1</id>
        <group>first</group>
    </element><element>
        <id>3</id>
        <group>first</group>
    </element></group>
    <group name="second"><element>
        <id>2</id>
        <group>second</group>
    </element></group>
</root>

请注意:

  1. Muenchian method for grouping的使用。这是 XSLT 1.0 中最有效的分组方法。

  2. AVT的使用 ( Attribute Value Template ) 将文字结果元素及其可变值属性指定为一个整体。使用 AVT 可简化编码并生成更短且更易于理解的代码。

二。一个更短的 XSLT 2.0 解决方案:

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/*">
     <root>
      <xsl:for-each-group select="element" group-by="group">
       <group name="{current-grouping-key()}">
        <xsl:copy-of select="current-group()"/>
       </group>
      </xsl:for-each-group>
     </root>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于同一个 XML 文档时(如上),将再次生成相同的正确结果。

请注意:

.1。 <xsl:for-each-group> 的使用 XSLT 2.0 指令。

.2。 标准XSLT 2.0函数的使用 current-group() current-grouping-key()

关于xml - 按 Xsl 中子项的值对 xml 节点进行分组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4711039/

相关文章:

xml - 根据属性值 XSLT 更改元素名称

xml - Xpath - 如何排除包含属性的节点?

java - 尽管我可以通过 xpath 选择元素,但在 Firefox 中获取 ElementNotVisibleException 异常

android - 在 android 中隐藏 Spinner 下拉图标

python - 什么是适用于 Python 的良好 XML 流解析器?

java - 使用自定义 XML 文件的 Android 滑动选项卡

regex - 可变数量的捕获组

xml - 如何检查 XSLT 中的 XML 值是否为 nil

xml - 从其他节点生成输出的 XSL 转换

xslt - xslt中多次出现相同的路径