如何将指定XML节点包装到单个<p>元素中?XSLT实现问题
XSLT节点合并解决方案
需要实现以下节点合并逻辑:
- 将
<p class="p1">节点、<div class="disp-quote-p">节点,以及紧跟在<div class="disp-quote-p">之后的第一个<p class="p1">节点,全部包装到一个新的<p>元素中 - 同时将
<div class="disp-quote-p">转换为<disp-quote>
输入XML
<root> <p class="p">aa</p> <p class="p1">Although:</p> <div class="disp-quote-p"> <p class="p">We had seen.</p> </div> <p class="p1">This dot.</p> <img src="a.png"/> <box>box</box> <p class="p">bb</p> </root>
当前错误的XSLT代码
<xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="root"> <xsl:copy> <xsl:for-each-group select="*" group-starting-with="p[@class='p1']"> <xsl:for-each-group select="current-group()" group-adjacent="self::p[@class='p1'] or self::div[@class='disp-quote-p']"> <xsl:choose> <xsl:when test="self::p[@class='p1']"> <p><xsl:apply-templates select="node(), current-group() except ."/></p> </xsl:when> <xsl:otherwise> <xsl:copy-of select="current-group()"/> </xsl:otherwise> </xsl:choose> </xsl:for-each-group> </xsl:for-each-group> </xsl:copy> </xsl:template>
预期输出
<root> <p class="p">aa</p> <p>Although:<disp-quote><p class="p">We had seen.</p></disp-quote>This dot.</p> <img src="a.png"/> <box>box</box> <p class="p">bb</p> </root>
正确的XSLT实现
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 身份模板,默认复制所有节点 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- 匹配root节点,处理分组逻辑 --> <xsl:template match="root"> <xsl:copy> <xsl:for-each-group select="*" group-starting-with="p[@class='p1']"> <xsl:choose> <!-- 匹配p1 -> div.disp-quote-p -> p1的连续节点序列 --> <xsl:when test="current-group() = (p[@class='p1'], div[@class='disp-quote-p'], p[@class='p1'])"> <p> <!-- 输出第一个p1的内容 --> <xsl:apply-templates select="current-group()[1]/node()"/> <!-- 将div转换为disp-quote并输出内部内容 --> <disp-quote> <xsl:apply-templates select="current-group()[2]/node()"/> </disp-quote> <!-- 输出第三个p1的内容 --> <xsl:apply-templates select="current-group()[3]/node()"/> </p> </xsl:when> <!-- 其他节点序列按默认规则处理 --> <xsl:otherwise> <xsl:apply-templates select="current-group()"/> </xsl:otherwise> </xsl:choose> </xsl:for-each-group> </xsl:copy> </xsl:template> <!-- 空模板匹配目标div,避免被身份模板重复复制 --> <xsl:template match="div[@class='disp-quote-p']"/> </xsl:stylesheet>
实现思路
- 以
<p class="p1">为分组起始点,将root的子节点分组,精准捕获目标节点序列 - 判断分组是否符合
p1 -> div.disp-quote-p -> p1的结构,若符合则合并到新<p>元素中,并完成div到disp-quote的转换 - 用空模板屏蔽目标div的默认复制逻辑,避免节点重复输出
- 非目标节点保持原有结构输出
内容的提问来源于stack exchange,提问作者Yug
相关产品推荐
相关产品推荐

