XSLT 1.0:如何移除关联特定学生的节点?是否使用键?
用XSLT 1.0的键(keys)实现指定节点的关联过滤
完全可以用XSLT 1.0的键(keys)来实现这个需求,而且键的方式能高效处理节点间的关联匹配,不用反复遍历节点,逻辑也更清晰。
原XML内容
<School> <Class name="Biology"/> <Class name="Math"/> <Class name="English"/> <Student className="Biology" Name="Chris"/> <Student className="English" Name="Kevin"/> <Student className="Biology" Name="Tania"/> <Student className="Math" Name="Kevin"/> <Student className="English" Name="Tania"/> </School>
实现的XSLT代码
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 给所有Tania所在的班级打标记,用className作为键值 --> <xsl:key name="tania-linked-classes" match="Student[@Name='Tania']" use="@className"/> <!-- 基础模板:默认复制所有节点和属性,没被特殊模板匹配的内容都保留 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- 移除所有被标记的班级 --> <xsl:template match="Class[key('tania-linked-classes', @name)]"/> <!-- 移除所有在被标记班级里的学生 --> <xsl:template match="Student[key('tania-linked-classes', @className)]"/> </xsl:stylesheet>
逻辑说明
- 键的作用:
tania-linked-classes键会收集所有Tania所在班级的名称,相当于给这些班级做了个全局标记,后续可以快速查询到哪些班级需要被处理。 - 基础复制规则:身份转换模板是XSLT的常用基础操作,确保那些不需要修改的节点能原封不动复制到输出里。
- 过滤Class节点:如果某个Class的名称在标记的班级列表里,这个模板会匹配它并直接跳过不输出,实现班级节点的移除。
- 过滤Student节点:同理,只要学生所在的班级在标记列表里,不管是不是Tania本人,都会被这个模板匹配并移除。
最终输出
运行上述XSLT后,得到的结果完全符合需求:
<School> <Class name="Math"/> <Student className="Math" Name="Kevin"/> </School>
内容的提问来源于stack exchange,提问作者Kieran Ojakangas
相关产品推荐
相关产品推荐

