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

XSLT新手求助:基于特定XML生成指定规则的转换脚本

XSLT实现按指定type提取并合并对应所有标签

我是XSLT新手,需要基于以下输入XML编写XSLT,实现提取type属性为指定值的对应的标签,并合并所有该类型之后到下一个之前的所有子标签(标签位置不固定,仅遵循“指定类型 + 该之后到下一个前的标签”的分组模式)。

输入XML

<root>
 <a>
    <b type="Test"></b>
  </a>
  <c></c>
  <d>
  </d>
  <e>
    <f>Test1</f>
    <f>Test2</f>
  </e>
  <e>
    <f>Test3</f>
    <f>Test4</f>
  </e>
  <e>
    <f>Test5</f>
  </e>

  <a>
    <b type="Rest"></b>
  </a>
  <c></c>
  <d>
  </d>
  <e>
    <f>Rest1</f>
    <f>Rest2</f>
  </e>
  <e>
    <f>Rest3</f>
    <f>Rest4</f>
  </e>
  <e>
    <f>Rest5</f>
  </e>

  <a>
    <b type="Host"></b>
  </a>
  <c></c>
  <d>
  </d>
  <e>
    <f>Hest1</f>
    <f>Hest2</f>
  </e>
  <e>
    <f>Hest3</f>
    <f>Hest4</f>
  </e>
  <e>
    <f>Hest5</f>
  </e>

  <a>
    <b type="Test"></b>
  </a>
  <c></c>
  <d>
  </d>
  <e>
    <f>Test6</f>
    <f>Test7</f>
  </e>
  <e>
    <f>Test8</f>
    <f>Test9</f>
  </e>
  <e>
    <f>Test10</f>
  </e>

  <a>
    <b type="Fest"></b>
  </a>
  <c></c>
  <d>
  </d>
  <e>
    <f>Fest1</f>
    <f>Fest2</f>
  </e>
  <e>
    <f>Fest3</f>
    <f>Fest4</f>
  </e>
  <e>
  <f>Fest5</f>
  </e>

</root>

期望输出示例(以type="Test"为例)

<b type="Test"></b>
<f>Test1</f> 
<f>Test2</f> 
<f>Test3</f> 
<f>Test4</f> 
<f>Test5</f> 
<f>Test6</f> 
<f>Test7</f> 
<f>Test8</f> 
<f>Test9</f> 
<f>Test10</f>

解决方案

方案1:XSLT 1.0版本(兼容大多数处理器)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <!-- 按<b>的type属性分组,快速定位目标type的<b> -->
    <xsl:key name="b-by-type" match="a/b" use="@type"/>
    
    <!-- 将每个<f>关联到它前面最近的<a>,通过唯一ID建立映射 -->
    <xsl:key name="f-for-a" match="f" use="generate-id(preceding-sibling::a[1])"/>
    
    <xsl:template match="/root">
        <!-- 这里替换为你需要提取的type值,比如'Test'、'Rest' -->
        <xsl:variable name="target-type" select="'Test'"/>
        
        <!-- 输出第一个匹配目标type的<b>(同type的<b>结构一致,只需输出一次) -->
        <xsl:copy-of select="key('b-by-type', $target-type)[1]"/>
        
        <!-- 遍历所有目标type的<a>,取出每个<a>对应的所有<f> -->
        <xsl:for-each select="a[b/@type = $target-type]">
            <xsl:copy-of select="key('f-for-a', generate-id(.))"/>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

方案2:XSLT 2.0+版本(语法更简洁)

如果你的XSLT处理器支持2.0及以上版本(比如Saxon),可以用for-each-group简化代码:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/root">
        <!-- 替换为目标type值 -->
        <xsl:variable name="target-type" select="'Test'"/>
        
        <!-- 输出目标type的<b>标签 -->
        <xsl:copy-of select="a[b/@type = $target-type]/b[1]"/>
        
        <!-- 以<a>为分组起点,把root下的节点分成多个组 -->
        <xsl:for-each-group select="*" group-starting-with="a">
            <!-- 如果当前组的<a>匹配目标type,输出组内所有<f> -->
            <xsl:if test="current-group()[1]/b/@type = $target-type">
                <xsl:copy-of select="current-group()//f"/>
            </xsl:if>
        </xsl:for-each-group>
    </xsl:template>
</xsl:stylesheet>

使用说明

  1. 修改代码中target-type变量的取值,即可切换提取不同type对应的内容;
  2. 使用XSLT处理器(如Saxon、Xalan)运行该XSLT文件,输入你的XML,就能得到期望的输出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 05:02:06