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

如何递归拼接当前节点所有前置兄弟节点的全部文本?

问题解决:拼接前置兄弟节点的全部文本内容

你的XML内容:

<?xml version="1.0"?>
<foo>
  <a>
   first
   <b>x</b>
   <c>y</c>
  </a>
  <b>second</b>
  <bar>hey</bar>
</foo>

你的XSL代码:

<?xml version="1.0"?>
<xsl:stylesheet 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
  <xsl:template match="/foo">
    <xsl:apply-templates select="bar" />
  </xsl:template>
  <xsl:template match="bar">
    [<xsl:value-of select="preceding-sibling::text()"/>]
  </xsl:template>
</xsl:stylesheet>

预期输出:

[first x y second]

问题分析

你当前代码里的preceding-sibling::text()只会选中bar节点前的直接文本节点,但你的前置兄弟是<a>和<b>这两个元素节点,它们的文本内容包含在自身及子节点中,所以这个选择器无法获取到目标内容。

解决方案

方案1:利用XSLT 2.0函数简洁实现

直接选择所有前置兄弟元素,提取它们包含的所有文本,清理多余空白后拼接:

<?xml version="1.0"?>
<xsl:stylesheet 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
  <xsl:template match="/foo">
    <xsl:apply-templates select="bar" />
  </xsl:template>
  
  <xsl:template match="bar">
    [<xsl:value-of select="string-join(preceding-sibling::*//text()/normalize-space(), ' ')"/>]
  </xsl:template>
</xsl:stylesheet>

方案2:递归拼接实现

如果需要严格用递归逻辑遍历前置兄弟节点并收集文本,可以用以下代码:

<?xml version="1.0"?>
<xsl:stylesheet 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
  <xsl:template match="/foo">
    <xsl:apply-templates select="bar" />
  </xsl:template>

  <xsl:template match="bar">
    [<xsl:call-template name="collect-prev-text">
      <xsl:with-param name="nodes" select="preceding-sibling::*"/>
    </xsl:call-template>]
  </xsl:template>

  <xsl:template name="collect-prev-text">
    <xsl:param name="nodes"/>
    <xsl:param name="result" select="''"/>
    <xsl:choose>
      <xsl:when test="$nodes">
        <xsl:variable name="current-text" select="normalize-space(string-join($nodes[1]//text(), ' '))"/>
        <xsl:call-template name="collect-prev-text">
          <xsl:with-param name="nodes" select="$nodes[position() > 1]"/>
          <xsl:with-param name="result" select="concat($result, if ($result) then ' ' else '', $current-text)"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$result"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

两种方案都能输出你预期的结果,前者借助XSLT 2.0的内置函数更简洁,后者完全通过递归逻辑实现文本拼接。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 12:43:16