You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用XSLT基于子字符串对XML数据进行分组

解决XML元素按名称子字符串分组的XSLT问题

问题描述

我想用XSLT把XML文档里的数据分成两类——建筑和食物。现有三个条目,希望通过元素名的子字符串来分组归类。

原始XML

<?xml version="1.0" encoding="UTF-8"?>
<items> 
    <Skyscraper>Willis Tower</Skyscraper> 
    <Small_fruit>blueberry</Small_fruit> 
    <Big_fruit>watermelon </Big_fruit> 
</items>

最初尝试的XSLT

<?xml version="1.1" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
    <xsl:output method="xml"/>  
    <xsl:template match = "/">      
        <items>
            <xsl:element name = "Fruit">
                <xsl:for-each-group select="//items" group-by="*[contains(local-name(), 'fruit')]">
                    <xsl:copy-of select = "."/>
                    <xsl:value-of select="current-grouping-key()"/>
                    <xsl:if test = "not(position() = last())">,</xsl:if>
                </xsl:for-each-group>
            </xsl:element>
        </items>
    </xsl:template> 
</xsl:stylesheet>

期望输出XML

<?xml version="1.0" encoding="UTF-8"?>
<items> 
    <Building>
        <Skyscraper>Willis Tower</Skyscraper>
    </Building> 
    <Food>
        <Small_fruit>blueberry</Small_fruit> 
        <Big_fruit>watermelon </Big_fruit> 
    </Food>
</items>

修改后的XSLT(仍有问题)

<?xml version="1.1" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
    <!-- airport XSLT -->
    <xsl:output method="xml"/>  
    <xsl:template match = "/">      
        <items>
            <xsl:element name = "fruit">
                <xsl:for-each-group select="/items/*" group-by="*[contains(local-name(), 'fruit')]">
                    <xsl:copy-of select = "."/>
                    <xsl:value-of select="current-grouping-key()"/>
                    <xsl:if test = "not(position() = last())">&#xa;</xsl:if>
                </xsl:for-each-group>
            </xsl:element>
            <xsl:element name = "building">
                <xsl:for-each-group select="/items/*" group-by="*[contains(local-name(), 'sky')]">
                    <xsl:copy-of select = "."/>
                    <xsl:value-of select="current-grouping-key()"/>
                    <xsl:if test = "not(position() = last())">&#xa;</xsl:if>
                </xsl:for-each-group>
            </xsl:element>
        </items>
    </xsl:template> 
</xsl:stylesheet>

正确的XSLT解决方案

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
    <xsl:output method="xml" indent="yes"/>  

    <xsl:template match="/">      
        <items>
            <!-- 按元素名特征分组:含'fruit'归Food组,其余归Building组 -->
            <xsl:for-each-group select="/items/*" group-by="if (contains(local-name(), 'fruit')) then 'Food' else 'Building'">
                <xsl:element name="{current-grouping-key()}">
                    <xsl:copy-of select="current-group()"/>
                </xsl:element>
            </xsl:for-each-group>
        </items>
    </xsl:template> 
</xsl:stylesheet>

方案说明

  • 一次性遍历所有子元素/items/*,避免重复扫描节点
  • 用条件表达式作为分组键,直接将元素归类到Food或Building组
  • 为每个分组创建对应名称的外层元素,复制组内所有原始元素,保留原有结构
  • 开启indent="yes"让输出格式与期望结果一致,更易读
  • 移除了多余的文本输出逻辑,确保结果纯净

内容的提问来源于stack exchange,提问作者n718an

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 02:35:30