如何在单次XSL转换中移除含全部skip属性子节点的Node2?
需求场景与问题
没问题!当然可以实现这个需求,只需要在你的XSL里再加一个匹配模板就行。先理清楚你的场景:你已经能移除带etv:severity="skip"属性的Node3节点,但现在发现有些Node2节点的所有子Node3都带有这个skip属性,希望在同一次转换中把这类空的Node2也一并删除。
原始XML
<Document> <Node1> <Node2> <Node3 etv:severity="ok"> stuff </Node3> <Node3 etv:severity="ok"> stuff </Node3> <Node3 etv:severity="skip"> stuff </Node3> </Node2> <Node2> <Node3 etv:severity="ok"> stuff </Node3> <Node3 etv:severity="ok"> stuff </Node3> <Node3 etv:severity="skip"> stuff </Node3> </Node2> <Node2> <Node3 etv:severity="skip"> stuff </Node3> <Node3 etv:severity="skip"> stuff </Node3> <Node3 etv:severity="skip"> stuff </Node3> </Node2> </Node1> </Document>
当前使用的XSL
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:etv="urn:com.etv/etv" xmlns:iso="urn:iso"> <xsl:output method="xml" indent="yes" /> <xsl:strip-space elements="*"/> <xsl:template match="@* | node()"> <xsl:copy> <xsl:apply-templates select="@*|node()" /> </xsl:copy> </xsl:template> <xsl:template match="/iso:Document/iso:Node1/iso:Node2/iso:Node3[(@etv:severity='skip')]" /> </xsl:stylesheet>
当前输出结果
<Document> <Node1> <Node2> <Node3 etv:severity="ok"> stuff </Node3> <Node3 etv:severity="ok"> stuff </Node3> </Node2> <Node2> <Node3 etv:severity="ok"> stuff </Node3> <Node3 etv:severity="ok"> stuff </Node3> </Node2> <Node2> </Node2> </Node1> </Document>
你希望移除最后那个空的Node2节点,因为它的所有子Node3都被移除了。
解决方案
只需要在你的XSL中新增一个匹配模板,专门针对那些**所有子Node3都带有etv:severity="skip"**的Node2节点。修改后的XSL如下:
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:etv="urn:com.etv/etv" xmlns:iso="urn:iso"> <xsl:output method="xml" indent="yes" /> <xsl:strip-space elements="*"/> <!-- 基础复制模板:保留所有未被匹配覆盖的节点和属性 --> <xsl:template match="@* | node()"> <xsl:copy> <xsl:apply-templates select="@*|node()" /> </xsl:copy> </xsl:template> <!-- 移除带有skip属性的Node3 --> <xsl:template match="/iso:Document/iso:Node1/iso:Node2/iso:Node3[@etv:severity='skip']" /> <!-- 移除所有子Node3都是skip的Node2 --> <xsl:template match="/iso:Document/iso:Node1/iso:Node2[not(iso:Node3[@etv:severity!='skip'])]" /> </xsl:stylesheet>
逻辑解释
新增的模板匹配条件/iso:Document/iso:Node1/iso:Node2[not(iso:Node3[@etv:severity!='skip'])]的意思是:
- 定位到所有Node2节点
- 检查这些Node2下是否不存在任何一个带有
etv:severity!='skip'(也就是severity为ok或其他非skip值)的Node3 - 如果符合这个条件(即所有Node3都是skip),这个空模板就会匹配该Node2,从而将其移除
最终输出
运行修改后的XSL后,你会得到如下结果,那个空的Node2已经被移除:
<Document> <Node1> <Node2> <Node3 etv:severity="ok"> stuff </Node3> <Node3 etv:severity="ok"> stuff </Node3> </Node2> <Node2> <Node3 etv:severity="ok"> stuff </Node3> <Node3 etv:severity="ok"> stuff </Node3> </Node2> </Node1> </Document>
内容的提问来源于stack exchange,提问作者TheUltimateHack
相关产品推荐
相关产品推荐

