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

如何用XSLT拼接跨页拆分的XML <par>节点值生成HTML段落?

解决方案:用XSLT合并跨页拆分的OCR段落

这个需求完全可以用XSLT实现,核心思路是按文档顺序遍历所有<par>节点,将属于同一个段落的节点分组合并,判断段落结束的依据是节点文本结尾为句点(可根据实际需求调整判断规则)。

方案1:XSLT 2.0(推荐,分组更简洁)

XSLT 2.0的xsl:for-each-group可以直接按段落结束条件分组,代码如下:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xmlns:x="http://www.abbyy.com/FineReader_xml/FineReader10-schema-v1.xml" 
                exclude-result-prefixes="x">
    <xsl:output omit-xml-declaration="yes" method="html" indent="yes"/>

    <xsl:template match="/">
        <xsl:for-each-group select="//x:par" group-ending-with="x:par[substring(., string-length(.)) = '.']">
            <p>
                <xsl:value-of select="current-group()" separator=" "/>
            </p>
            <xsl:text>&#xa;</xsl:text>
        </xsl:for-each-group>
    </xsl:template>
</xsl:stylesheet>

代码说明:

  • //x:par:按文档顺序选中所有<par>节点,不管它们在哪个<page>或<block>下
  • group-ending-with="x:par[substring(., string-length(.)) = '.']":将以句点结尾的<par>作为每组的最后一个节点,自动把前面连续的非结尾<par>归为同一组
  • current-group():获取当前组的所有<par>节点,用separator=" "将文本用空格连接

方案2:XSLT 1.0(适配xsltproc等1.0处理器)

XSLT 1.0没有原生分组功能,可通过递归模板实现遍历合并:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xmlns:x="http://www.abbyy.com/FineReader_xml/FineReader10-schema-v1.xml" 
                exclude-result-prefixes="x">
    <xsl:output omit-xml-declaration="yes" method="html"/>

    <!-- 匹配根节点,启动递归处理第一个par -->
    <xsl:template match="/">
        <xsl:apply-templates select="(//x:par)[1]" mode="merge"/>
    </xsl:template>

    <!-- 递归合并段落的模板 -->
    <xsl:template match="x:par" mode="merge">
        <xsl:variable name="current-par" select="."/>
        <!-- 收集当前par及后续连续的非结尾par -->
        <xsl:variable name="merged-text">
            <xsl:call-template name="collect-pars">
                <xsl:with-param name="start-par" select="$current-par"/>
            </xsl:call-template>
        </xsl:variable>
        <!-- 输出合并后的段落 -->
        <p><xsl:value-of select="$merged-text"/></p>
        <xsl:text>&#xa;</xsl:text>
        <!-- 处理下一个未合并的par -->
        <xsl:apply-templates select="$current-par/following::x:par[count(preceding::x:par) = count($current-par/preceding::x:par) + count($current-par/following::x:par[substring(., string-length(.)) != '.']) + 1]" mode="merge"/>
    </xsl:template>

    <!-- 递归收集连续的非结尾par文本 -->
    <xsl:template name="collect-pars">
        <xsl:param name="start-par"/>
        <xsl:value-of select="$start-par"/>
        <xsl:if test="substring($start-par, string-length($start-par)) != '.'">
            <xsl:text> </xsl:text>
            <xsl:call-template name="collect-pars">
                <xsl:with-param name="start-par" select="$start-par/following::x:par[1]"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

代码说明:

  • 用mode="merge"区分普通模板和合并模板,避免冲突
  • collect-pars模板递归收集当前<par>及后续所有非结尾的<par>文本,直到遇到以句点结尾的节点
  • 主递归模板输出合并后的段落,再定位到下一个未处理的<par>继续处理

解决你之前的问题

你之前的代码用following-sibling只能处理同一<block>下的兄弟节点,跨页的<par>不属于兄弟节点,所以无法匹配。上述两种方案用//x:par(2.0)或following::x:par(1.0)遍历所有文档顺序的<par>节点,解决了跨页节点无法访问的问题。

测试示例

输入(你提供的简化文档):

<document xmlns="http://www.abbyy.com/FineReader_xml/FineReader10-schema-v1.xml">
    <page>
        <block>
            <par>This is a line.</par>
            <par>This is a line</par>
            <par>that is split.</par>
        </block>
    </page>
    <page>
        <block>
            <par>line split</par>
        </block>
    </page>
    <page>
        <block>
            <par>across pages.</par>
        </block>
    </page>
</document>

输出(与你的理想结果一致):

<p>This is a line.</p>
<p>This is a line that is split.</p>
<p>line split across pages.</p>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 06:22:06