XSLT 3.0按<eop>标签分页:调用特定元素时分组分页失效的解决方案咨询
你遇到的核心问题在于:当你从使用<xsl:apply-templates select="current-group()"/>改为只选择title和article元素时,整个article被当作一个完整节点处理,导致它内部的<eop eId="101">无法触发分页,最终页面内容跨页显示,打破了预期的分页逻辑。
问题根源分析
你的分组逻辑本身是正确的——通过group-starting-with="eop"把所有节点按<eop>分割成不同页面组。但当你使用current-group()/self::article时,你选择的是整个article元素节点,而这个元素包含了属于下一个页面组的子节点(比如嵌套在<p>里的<eop eId="101">以及后面的内容)。当你对这个完整的article元素应用模板时,它会遍历并输出所有子节点,包括那些本该属于下一页的内容,自然就破坏了分页逻辑。
解决方案
你需要避免选择整个article元素,而是让每个页面组只处理属于自己范围内的节点。如果你想保持分页逻辑正常,同时控制内容的显示顺序(比如先显示title再显示其他内容),可以这样修改dataRoot模板:
修改后的XSLT代码片段
<xsl:template match="dataRoot"> <xsl:for-each-group select=".//node()" group-starting-with="eop"> <div class="page"> <div class="content"> <!-- 先处理当前组内的所有title节点 --> <xsl:apply-templates select="current-group()[self::title]"/> <!-- 处理当前组内除title外的其他节点(包括eop、article的部分内容等) --> <xsl:apply-templates select="current-group()[not(self::title)]"/> </div> </div> </xsl:for-each-group> </xsl:template>
如果你不需要调整显示顺序,直接恢复使用原来的写法即可,它会按文档顺序处理当前组内的所有节点,自然保证分页正确:
<xsl:apply-templates select="current-group()"/>
这样修改后,分页逻辑就能恢复正常:
- 第一页(eop100组)会显示页码100,以及
<eop eId="101">之前的article 1内容; - 第二页(eop101组)会显示页码101,以及
<eop eId="101">之后的article 1剩余内容和article 2的内容,完全符合你的预期。
额外说明
你的XML里<eop>节点嵌套在<p>元素内部,这并不影响分组逻辑——因为group-starting-with="eop"是基于所有节点的文档顺序来分组的,不管它的嵌套层级如何,只要遇到<eop>就会开启新页面。
内容的提问来源于stack exchange,提问作者OrYo

