You need to enable JavaScript to run this app. XSLT结合following-sibling与递归模板实现XML语料分句抓取
优惠活动
大模型
产品
解决方案
定价
更多

XSLT结合following-sibling与递归模板实现XML语料分句抓取

问题解决思路

不需要编写复杂的递归模板,针对你当前的XSLT 2.0版本,使用内置的相邻节点分组能力就能直接实现全文档分句,同时一次性解决现有代码的两个缺陷。

现有代码的问题根因

  • 仅输出第一句内容:你当前使用的XPath表达式//w[not(contains(./forme, '.'))][following-sibling::*[1][contains(./forme, '.')]]本质是筛选“下一个相邻节点是句末句号”的单词节点,既无法抓取长句子中离句号较远的单词,也没有对多句边界做批量遍历,实际只能匹配到每句中倒数第二个单词节点,根本覆盖不了完整句子范围。
  • 缺失句末带.的节点:你的XPath通过not(contains(./forme, '.'))直接过滤掉了所有带句号的节点,自然无法把句末的标点节点纳入结果。

适配语料结构的实现方案

你的语料结构是根节点<cordial2xml>下连续排布平级的<w>节点,分句的核心判断规则非常明确:只要<w>节点的<forme>值为.,就是当前句子的结束边界;从文档起始位置、上一个句末边界之后,到当前句末节点为止的所有连续<w>,共同组成一个完整句子。
这类连续序列切分场景,用XSLT 2.0的for-each-group做相邻分组是最简洁、学习成本最低的方案,不需要手写递归逻辑:

  • 以“节点前面出现过的句末句号累计数量”作为分组键,自然把所有连续的同句子节点归到同一组
  • 分组过程会自动把带.的句末节点纳入所属句子的组内,不会遗漏
  • 可以一次性遍历文档所有<w>节点,不存在只处理第一句的问题

可直接运行的修正版XSLT代码

<xsl:stylesheet version="2.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" encoding="utf-8" indent="yes"/>
  
  <xsl:template match="/">
    <xsl:text disable-output-escaping='yes'>&lt;!DOCTYPE html&gt;</xsl:text>
    <html>
      <head>
        <title>分句结果</title>
      </head>
      <body>
        <h1>Poème du Père Duchesne</h1>
        <!-- 以句末累计计数为键,对所有w节点做相邻分组 -->
        <xsl:for-each-group select="cordial2xml/w" 
                            group-adjacent="count(preceding-sibling::w[normalize-space(forme) = '.'])">
          <!-- 每一个分组对应一个完整句子,单独包裹为段落 -->
          <p class="sentence">
            <!-- 遍历组内所有w节点,拼接词形,同时保留词元、词性信息 -->
            <xsl:for-each select="current-group()">
              <span class="word">
                <xsl:value-of select="forme"/>
                <!-- NLP语料扩展输出:需要保留标注时打开下方注释 -->
                <!-- 
                <small>
                  (lemme: <xsl:value-of select="lemme"/>, 
                  categorie: <xsl:value-of select="categorie"/>)
                </small>
                -->
              </span>
              <xsl:if test="position() != last()">
                <xsl:text xml:space="preserve"> </xsl:text>
              </xsl:if>
            </xsl:for-each>
          </p>
        </xsl:for-each-group>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

补充说明

如果后续需要适配更复杂的句末边界规则(比如把!、?也作为句末标记),只需要修改分组键里的判断条件normalize-space(forme) = '.'为('.', '!', '?')[. = normalize-space(forme)]即可,不需要重写整体逻辑。
手写递归模板本质是手动维护游标位置、逐节点判断边界的过程,对于仅学习一周XSLT的开发者来说,调试成本高、容易出现边界判断错误,不推荐作为优先实现方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.25 20:45:06