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

如何用XSLT将两个逗号分隔标签拆分为父子标签列表?

解决逗号分隔字符串拆分为平级标签列表的问题

我懂你现在的困扰——你想把<UserID>162,163</UserID>和<UserName>Stacy,Stephen</UserName>这两个逗号分隔的字符串,转换成一组平级的<User>标签,每个<User>里对应包含<ID>和<Name>,但当前的XSLT模板生成了嵌套的<User>结构,而不是你想要的列表形式对吧?

问题根源分析

你当前的模板把<User>标签放在了递归调用的内部,每次递归生成新的<User>时都会嵌套到上一个<User>里面,自然就出现了嵌套结构。正确的思路应该是先把两个字符串分别拆成对应位置的序列/节点集,再逐个匹配生成平级的标签。

下面分两种XSLT版本给出解决方案:


方案1:XSLT 1.0 兼容版本(适合旧版处理器)

XSLT 1.0没有内置的字符串拆分函数,我们需要用递归模板先把两个字符串拆成节点集,再通过位置匹配来生成对应:

第一步:通用字符串拆分模板

这个模板会把输入的逗号分隔字符串转换成<item>节点的集合:

<xsl:template name="tokenize-string">
  <xsl:param name="text" select="''"/>
  <xsl:param name="separator" select="','"/>
  <xsl:if test="$text != ''">
    <!-- 提取当前分隔符前的内容,去除前后空格 -->
    <item>
      <xsl:value-of select="normalize-space(substring-before(concat($text, $separator), $separator))"/>
    </item>
    <!-- 递归处理剩余的字符串 -->
    <xsl:call-template name="tokenize-string">
      <xsl:with-param name="text" select="substring-after($text, $separator)"/>
      <xsl:with-param name="separator" select="$separator"/>
    </xsl:call-template>
  </xsl:if>
</xsl:template>

第二步:主模板生成列表

调用上面的模板拆分ID和Name,再遍历匹配位置生成平级:

<xsl:template match="/">
  <Users>
    <!-- 拆分UserID为节点集 -->
    <xsl:variable name="id-nodes">
      <xsl:call-template name="tokenize-string">
        <xsl:with-param name="text" select="UserID"/>
      </xsl:call-template>
    </xsl:variable>
    <!-- 拆分UserName为节点集 -->
    <xsl:variable name="name-nodes">
      <xsl:call-template name="tokenize-string">
        <xsl:with-param name="text" select="UserName"/>
      </xsl:call-template>
    </xsl:variable>

    <!-- 遍历ID节点,按位置匹配对应的Name节点 -->
    <xsl:for-each select="$id-nodes/item">
      <xsl:variable name="current-pos" select="position()"/>
      <User>
        <ID><xsl:value-of select="."/></ID>
        <Name><xsl:value-of select="$name-nodes/item[$current-pos]"/></Name>
      </User>
    </xsl:for-each>
  </Users>
</xsl:template>

方案2:XSLT 2.0+ 简化版本(适合新版处理器)

XSLT 2.0及以上版本内置了tokenize()函数,可以直接把字符串拆成序列,代码会简洁很多:

<xsl:template match="/">
  <Users>
    <!-- 拆分ID和Name为字符串序列,自动处理逗号前后的空格 -->
    <xsl:variable name="id-sequence" select="tokenize(normalize-space(UserID), '\s*,\s*')"/>
    <xsl:variable name="name-sequence" select="tokenize(normalize-space(UserName), '\s*,\s*')"/>

    <!-- 遍历序列位置,生成对应<User> -->
    <xsl:for-each select="1 to count($id-sequence)">
      <xsl:variable name="current-pos" select="."/>
      <User>
        <ID><xsl:value-of select="$id-sequence[$current-pos]"/></ID>
        <Name><xsl:value-of select="$name-sequence[$current-pos]"/></Name>
      </User>
    </xsl:for-each>
  </Users>
</xsl:template>

效果验证

对于输入:

<Root>
  <UserID>162,163</UserID>
  <UserName>Stacy,Stephen</UserName>
</Root>

两个方案都会输出你期望的结果:

<Users>
  <User>
    <ID>162</ID>
    <Name>Stacy</Name>
  </User>
  <User>
    <ID>163</ID>
    <Name>Stephen</Name>
  </User>
</Users>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:43:55