如何通过XSLT将<section>间的同级元素移入对应<section>节点内?
需求实现:迁移夹在之间的兄弟节点到对应内
需要完成的操作:把所有同时是某<section>的前置兄弟节点,且是另一<section>的后置兄弟节点的标签,移入对应的<section>内部。
示例输入XML
<root> <section id="s1">原有内容</section> <p>这是s1后面的段落</p> <note>这是s1后面的注释</note> <section id="s2"/> <div>这是s2后面的div</div> <section id="s3">s3的内容</section> </root>
预期输出XML
<root> <section id="s1">原有内容 <p>这是s1后面的段落</p> <note>这是s1后面的注释</note> </section> <section id="s2"> <div>这是s2后面的div</div> </section> <section id="s3">s3的内容</section> </root>
当前待完善的XSLT代码
<xsl:stylesheet version="1.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> <!-- 缺少迁移节点的核心逻辑 --> </xsl:stylesheet>
完善后的XSLT解决方案
<xsl:stylesheet version="1.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> <!-- 处理<section>节点,将后续非<section>兄弟节点移入内部 --> <xsl:template match="section"> <xsl:copy> <!-- 复制当前section的属性 --> <xsl:apply-templates select="@*"/> <!-- 先输出原section内部的内容 --> <xsl:apply-templates select="node()"/> <!-- 选取当前section到下一个section之间的所有非<section>兄弟节点 --> <xsl:apply-templates select="following-sibling::*[not(self::section) and generate-id(following-sibling::section[1]) = generate-id(current()/following-sibling::section[1])]"/> </xsl:copy> </xsl:template> <!-- 跳过已迁移的非<section>节点,避免重复输出 --> <xsl:template match="*[not(self::section) and preceding-sibling::section and following-sibling::section]"/> </xsl:stylesheet>
关键逻辑说明
- 身份模板:作为XSLT基础规则,保证原有XML结构和内容的完整复制。
- section处理模板:
- 先复制当前section的标签与属性,再输出其原有内部内容。
- 通过
generate-id精准匹配当前section到下一个section之间的非section节点,确保只迁移对应区间的内容。
- 跳过节点模板:夹在两个section之间的非section节点已被移入前一个section,直接跳过不输出,防止重复。
该方案兼容XSLT 1.0,若使用2.0+版本可进一步简化节点选取逻辑,但此写法兼容性更强。
内容的提问来源于stack exchange,提问作者Kitabuddin
相关产品推荐
相关产品推荐

