如何通过XSLT基于子节点文本条件筛选XML节点并完成指定转换?
问题解决:针对特定条件的XML节点修改XSLT方案
需求回顾
给定XML文件,需仅处理FgOrComponent值为FG的Part元素:
- 将
number节点重命名为name - 将
DefaultUnit的内容改为ea - 为空的
MasterPackUom设置值mp - 为空的
CartonUom设置值ca
其余Part元素保持原样。
原XSLT的问题分析
- 上下文判断错误:模板匹配
/*/*/Part[(FgOrComponent = 'FG')]/*时,当前上下文是Part的子节点(如number、DefaultUnit等),此时MasterPackUom/text() = ''的判断是在当前子节点下查找MasterPackUom,而非直接判断当前节点是否为空,导致条件永远不触发。 - 需求覆盖不全:未处理
number重命名、DefaultUnit值修改的逻辑,也遗漏了CartonUom的处理。 - 节点处理逻辑错误:使用
<xsl:value-of select="."/>会丢失元素结构,额外的<xsl:apply-templates/>会导致节点重复处理。
正确的XSLT实现
<?xml version="1.0" encoding="iso-8859-1"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/> <!-- 身份模板:默认复制所有未被特殊匹配的节点 --> <xsl:template match="node()|@*"> <xsl:copy> <xsl:apply-templates select="node()|@*"/> </xsl:copy> </xsl:template> <!-- 将FG类型Part下的number节点重命名为name --> <xsl:template match="Part[FgOrComponent='FG']/number"> <name> <xsl:value-of select="."/> </name> </xsl:template> <!-- 修改FG类型Part下的DefaultUnit值为ea --> <xsl:template match="Part[FgOrComponent='FG']/DefaultUnit"> <DefaultUnit>ea</DefaultUnit> </xsl:template> <!-- 为空的FG类型Part下的MasterPackUom设置值mp --> <xsl:template match="Part[FgOrComponent='FG']/MasterPackUom[not(text())]"> <MasterPackUom>mp</MasterPackUom> </xsl:template> <!-- 为空的FG类型Part下的CartonUom设置值ca --> <xsl:template match="Part[FgOrComponent='FG']/CartonUom[not(text())]"> <CartonUom>ca</CartonUom> </xsl:template> </xsl:stylesheet>
工作原理说明
- 身份模板:确保所有不需要修改的节点(如
COMPONENT类型的Part及其子节点、FG类型Part下的FgOrComponent节点)都被原样复制,满足“其余元素保持不变”的要求。 - 针对性模板:每个模板仅匹配需要修改的特定节点,精准控制修改逻辑,避免不必要的节点处理:
- 重命名节点时直接创建新元素并保留原内容
- 修改值时直接替换内容
- 为空节点赋值时通过
not(text())判断节点是否无文本内容,仅在满足条件时修改。
内容的提问来源于stack exchange,提问作者Srinivasan Bhaskaran
相关产品推荐
相关产品推荐

