XSLT 2/3 如何拆分混合内容元素为独立句子元素(仅按直接文本内句号分割)
混合内容节点按直接文本句号拆分的实现方案
核心规则落地逻辑
- 仅对待拆分节点(示例中为
<p>)的直接子文本节点做句号切分,所有嵌套子元素、孙元素内部的句号完全不做处理,原样保留 - 先将切分后的文本片段和原有子元素按原始顺序组成节点序列,再按“当前节点之前累计遇到的直接文本句号数量”给相邻节点分组,同一组内容对应一个独立的
<sentence>元素
可直接运行的XSLT 2.0代码
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 保留所有缩进、换行空白,避免格式丢失 --> <xsl:strip-space elements=""/> <!-- 匹配根text节点 --> <xsl:template match="text"> <text> <xsl:apply-templates select="p"/> </text> </xsl:template> <!-- 匹配待拆分的p节点 --> <xsl:template match="p"> <!-- 预处理节点:拆分直接子文本的句号,子元素原样保留 --> <xsl:variable name="preprocessed-nodes"> <xsl:for-each select="node()"> <!-- 处理直接子文本节点:按句号拆分,保留句号本身 --> <xsl:if test="self::text()"> <xsl:analyze-string select="." regex="([^.]*\.)|([^.]+)"> <xsl:matching-substring> <!-- 跳过空匹配片段,保留有效空白 --> <xsl:if test="normalize-space(.) ne '' or matches(., '^\s+$')"> <xsl:copy-of select="."/> </xsl:if> </xsl:matching-substring> </xsl:analyze-string> </xsl:if> <!-- 处理子元素:完全原样复制 --> <xsl:if test="self::element()"> <xsl:copy-of select="."/> </xsl:if> </xsl:for-each> </xsl:variable> <!-- 按句号位置邻接分组,生成sentence节点 --> <xsl:for-each-group select="$preprocessed-nodes/node()" group-adjacent="sum(preceding-sibling::node()[self::text() and matches(., '\.$')]/count(.)) + 1" > <sentence> <xsl:copy-of select="current-group()"/> </sentence> </xsl:for-each-group> </xsl:template> </xsl:stylesheet>
效果验证说明
- 示例中
<d>元素内部的“sunt in.”句号属于子元素内部文本,不会被作为拆分标记,整个<d>元素会完整保留在最后一个<sentence>中,完全符合拆分要求
内容的提问来源于stack exchange,提问作者martinanton
相关产品推荐
相关产品推荐

