XSLT实现父节点复制到子节点且不重复复制子节点
解决XML父节点内容复制到子节点(排除子节点本身)的XSLT问题
需求概述
需要将<FoodGroups>节点的内容(排除其下的<FoodGroup>子节点)复制到每个<FoodGroup>内部,同时重新组织XML结构。
原始XML输入
<FoodGroups> <Nutritional>Yes</Nutritional> <Artifical>No</Artificial> <FoodGroup> <Fruit>Grape</Fruit> <Fruit>Apple</Fruit> </FoodGroup> <FoodGroup> <Vegetable>Carrot</Vegetable> <Vegetable>Potato</Vegetable> </FoodGroup> </FoodGroups>
期望输出XML
<xml> <FoodGroup> <Fruit>Grape</Fruit> <Fruit>Apple</Fruit> <FoodGroups> <Nutritional>Yes</Nutritional> <Artificial>No</Artificial> </FoodGroups> </FoodGroup> <FoodGroup> <Vegetable>Carrot</Vegetable> <Vegetable>Potato</Vegetable> <FoodGroups> <Nutritional>Yes</Nutritional> <Artificial>No</Artificial> </FoodGroups> </FoodGroup> </xml>
原代码错误分析
你之前的XSLT代码存在两个核心问题:
- 筛选
<FoodGroups>子节点的逻辑错误://FoodGroups/*[not(child::FoodGroup)]的含义是选择所有没有<FoodGroup>子元素的节点,但实际上我们需要排除的是<FoodGroups>下直接的<FoodGroup>节点本身,而非节点内容里包含<FoodGroup>的元素。 - 没有将筛选后的节点重新包裹在
<FoodGroups>标签内,导致输出结构不符合预期。
修正后的XSLT代码
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="msxsl"> <xsl:output omit-xml-declaration="yes" method="xml" indent="yes"/> <!-- 定义变量存储FoodGroups下的非FoodGroup子节点 --> <xsl:variable name="foodGroupsMetadata" select="/FoodGroups/*[name() != 'FoodGroup']"/> <xsl:template match="/"> <xml> <xsl:apply-templates select="/FoodGroups/FoodGroup"/> </xml> </xsl:template> <xsl:template match="FoodGroup"> <FoodGroup> <!-- 复制当前FoodGroup的所有子节点 --> <xsl:copy-of select="./*"/> <!-- 重新创建FoodGroups节点并插入预存的元数据 --> <FoodGroups> <xsl:copy-of select="$foodGroupsMetadata"/> </FoodGroups> </FoodGroup> </xsl:template> </xsl:stylesheet>
关键优化点
- 使用变量
$foodGroupsMetadata提前存储需要复制的元数据,避免重复查询,提升效率。 - 筛选逻辑改为
/FoodGroups/*[name() != 'FoodGroup'],精准排除<FoodGroups>下直接的<FoodGroup>子节点。 - 手动创建
<FoodGroups>标签并插入元数据,保证输出结构与预期一致。
处理多层嵌套场景
如果<FoodGroup>内部存在多层嵌套的子<FoodGroup>,该代码依然有效:因为我们的元数据变量仅筛选根<FoodGroups>下的非<FoodGroup>节点,不会影响内部嵌套的<FoodGroup>结构,只会将顶层元数据复制到每个最外层的<FoodGroup>中。
验证输出
运行修正后的XSLT,将得到与期望完全一致的XML结构。
内容的提问来源于stack exchange,提问作者Kieran Ojakangas
相关产品推荐
相关产品推荐

