使用XSLT降级XML版本时迁移节点并按需创建目标节点的方法咨询
XSLT节点迁移解决方案(兼容1.0/2.0+)
核心思路
用身份模板复制文档中大部分节点,仅对<a>节点做特殊处理:
- 检查
<a>下是否存在<b>或<c>节点(任意一个存在即可) - 若存在,生成
<d><e>...</e></d>结构,并将<b>、<c>移入其中 - 保留
<a>下除<b>、<c>外的所有其他节点 - 若
<b>和<c>都不存在,完全保留原<a>结构
XSLT 1.0 实现代码
<?xml version="1.0" encoding="UTF-8"?> <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> <!-- 匹配<a>节点,处理b/c的迁移 --> <xsl:template match="a"> <xsl:copy> <!-- 仅当存在b或c时,生成d/e结构 --> <xsl:if test="b or c"> <d> <e> <xsl:apply-templates select="b|c"/> </e> </d> </xsl:if> <!-- 复制a下除b/c外的所有子节点 --> <xsl:apply-templates select="node()[not(self::b or self::c)]"/> </xsl:copy> </xsl:template> <!-- 空模板:防止b/c被身份模板重复复制 --> <xsl:template match="b|c"/> </xsl:stylesheet>
测试验证
测试用例1:仅含b/c的输入
输入:
<a> <b>123</b> <c>456</c> </a>
输出:
<a> <d> <e> <b>123</b> <c>456</c> </e> </d> </a>
测试用例2:含b/c和其他节点的输入
输入:
<a> <b>123</b> <f>789</f> <c>456</c> </a>
输出:
<a> <d> <e> <b>123</b> <c>456</c> </e> </d> <f>789</f> </a>
测试用例3:无b/c的输入
输入:
<a><f>789</f></a>
输出:
<a><f>789</f></a>
XSLT 2.0+ 简化写法
如果可以使用XSLT 2.0及以上版本,代码可以更简洁(利用xsl:sequence和更灵活的节点选择):
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:mode on-no-match="shallow-copy"/> <xsl:template match="a"> <xsl:copy> <xsl:if test="b or c"> <d> <e> <xsl:sequence select="b, c"/> </e> </d> </xsl:if> <xsl:sequence select="node()[not(self::b or self::c)]"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
内容的提问来源于stack exchange,提问作者user2214829
相关产品推荐
相关产品推荐

