如何将block元素分组到<p class="p">内?求替代XSLT实现方案
问题:合并特定XML节点的XSLT替代写法
需求说明
将<block>元素以及后续的<p class="p1">内容合并到前置的<p class="p">元素内部,触发条件为:<p class="p">的第一个后续兄弟节点是<block>元素。
输入XML文件
<root> <p class="p">aaaaaa</p> <block> <p>block</p> </block> <p class="p1"> bbb </p> <block> <p>block</p> </block> <p class="p1">bbb.</p> <p class="p">cccc</p> </root>
期望输出XML文件
<root> <p class="p">aaaaaa<block><p>block</p></block> bbb <block><p>block</p></block>bbb.</p> <p class="p">cccc</p> </root>
当前使用的XSLT代码
<xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="p[@class='p']"> <xsl:choose> <xsl:when test="following-sibling::*[1][self::block]"> <xsl:text disable-output-escaping="yes"><p></xsl:text> <xsl:apply-templates/> </xsl:when> <xsl:otherwise> <p><xsl:apply-templates select="@*|node()"/></p> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="p[@class='p1']"> <xsl:choose> <xsl:when test="following-sibling::*[1][self::p[@class='p']]"> <xsl:apply-templates/> <xsl:text disable-output-escaping="yes"></p></xsl:text> </xsl:when> <xsl:otherwise> <xsl:apply-templates/> </xsl:otherwise> </xsl:choose> </xsl:template>
更规范的替代写法
你当前的写法依赖disable-output-escaping手动拼接XML标签,这种方式不够健壮,容易导致输出XML格式错误。推荐使用XSLT标准的节点处理逻辑实现,以下是替代方案:
<!-- 身份模板,默认复制所有节点和属性 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- 匹配需要合并的p[@class='p']节点 --> <xsl:template match="p[@class='p'][following-sibling::*[1][self::block]]"> <p class="p"> <!-- 处理当前p节点的内容 --> <xsl:apply-templates select="node()"/> <!-- 处理后续所有非p[@class='p']的兄弟节点,用merge模式 --> <xsl:apply-templates select="following-sibling::*[not(self::p[@class='p'])]" mode="merge"/> </p> </xsl:template> <!-- merge模式:直接复制block和p1节点 --> <xsl:template match="block|p[@class='p1']" mode="merge"> <xsl:copy-of select="."/> </xsl:template> <!-- 阻止被合并的原block和p1节点输出 --> <xsl:template match="block[preceding-sibling::*[1][self::p[@class='p']]]|p[@class='p1'][preceding-sibling::block]"/>
逻辑说明
- 匹配符合触发条件的
<p class="p">节点,复制该节点并在其内部先处理自身内容。 - 通过
merge模式,将后续所有<block>和<p class="p1">节点直接复制到当前<p class="p">内部。 - 最后编写模板,让原本要被合并的
<block>和<p class="p1">节点不再单独输出,避免重复。
这种写法完全基于XSLT的节点处理机制,输出的XML结构更可靠,也更易于维护。
内容的提问来源于stack exchange,提问作者Yug
相关产品推荐
相关产品推荐

