如何使用XSLT调整XML中entryprofile与node元素的层级关系?
XML转换问题分析与解决方案
需求说明
需要将XML中每个student节点下的entryprofile元素修改为包含同级的node元素,同时保留student下的name、age、ages元素,移除原来独立的node节点。
原始XML输入
<?xml version="1.0" encoding="utf-16"?> <class> <student> <name>Ben</name> <age>1</age> <ages>4</ages> <entryprofile></entryprofile> <node>1</node> </student> <student> <name>Steve</name> <age>2</age> <ages>3</ages> <entryprofile></entryprofile> <node>1</node> </student> </class>
你当前代码的问题
你写的XSLT存在以下几个核心问题:
- 完全丢失了
student和外层class的层级结构,直接输出零散节点,偏离预期格式 - 未处理
age、ages元素,导致这些必要节点被丢弃 - 错误添加了不必要的
new-level节点,且未将node移入entryprofile - 没有利用XSLT的基础模板机制保留原有结构,仅处理了极小部分节点
你尝试的错误XSLT代码
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="student"> <xsl:copy-of select="name"/> <new-level> <xsl:copy-of select="entryprofile"/> </new-level> </xsl:template> </xsl:stylesheet>
正确的XSLT实现
以下是符合需求的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> <!-- 处理entryprofile:复制自身后,将同级的node节点移入其中 --> <xsl:template match="entryprofile"> <xsl:copy> <xsl:apply-templates select="../node"/> </xsl:copy> </xsl:template> <!-- 匹配独立的node节点,不输出即移除 --> <xsl:template match="node"/> </xsl:stylesheet>
代码解释
- 身份模板:这是XSLT的基础模板,会自动保留
class、student、name、age、ages等所有未被特殊模板匹配的节点,保证原有层级结构不变。 - entryprofile模板:匹配到
entryprofile节点时,先复制该节点,再将其父节点(student)下的node节点复制到entryprofile内部。 - node模板:匹配独立的
node节点时不做任何输出,实现移除该节点的效果。
运行这段XSLT后,就能得到你预期的输出结果:
<?xml version="1.0" encoding="utf-16"?> <class> <student> <name>Ben</name> <age>1</age> <ages>4</ages> <entryprofile> <node>1</node> </entryprofile> </student> <student> <name>Steve</name> <age>2</age> <ages>3</ages> <entryprofile> <node>1</node> </entryprofile> </student> </class>
内容的提问来源于stack exchange,提问作者Benjamin Hammond
相关产品推荐
相关产品推荐

