使用XSLT 2.0按属性与文本匹配移除XML节点的技术问题
问题分析与解决方案
你的核心问题是当前的XSLT模板直接删除了整个teacher节点(只要它包含符合条件的situation),但你实际需求是删除teacher下的特定situation子节点,仅当删除后该teacher没有剩余situation时才移除整个teacher节点。
错误原因
你的现有模板:
<xsl:template match="teacher[starts-with(@id,'A2') and situation/ill='yes']"/> <xsl:template match="teacher[starts-with(@id,'G5') and situation/ill='probable']"/>
这段代码的逻辑是:只要某个teacher节点满足“id以A2开头且存在ill为yes的situation”,就直接删除整个teacher,而不是只删除那个符合条件的situation。这就是为什么所有A254的teacher都被删掉了,因为它们都包含符合条件的situation节点。
正确的XSLT实现
我们需要分两步处理:
- 先删除符合条件的
situation节点 - 再删除那些删除了所有
situation后变成空的teacher节点
完整代码如下:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> <!-- 身份转换模板:默认复制所有节点和属性 --> <xsl:template match="node()|@*"> <xsl:copy> <xsl:apply-templates select="node()|@*"/> </xsl:copy> </xsl:template> <!-- 1. 删除id以"A2"开头的teacher下,ill为"yes"的situation节点 --> <xsl:template match="teacher[starts-with(@id, 'A2')]/situation[ill='yes']"/> <!-- 2. 删除id以"G5"开头的teacher下,ill为"probable"的situation节点 --> <xsl:template match="teacher[starts-with(@id, 'G5')]/situation[ill='probable']"/> <!-- 3. 删除没有任何situation子节点的teacher节点 --> <xsl:template match="teacher[not(situation)]"/> </xsl:stylesheet>
转换结果验证
使用上述代码处理你的原始XML后,会得到你期望的结果:
<?xml version="1.0" encoding="UTF-8"?> <root> <organisation> <school> <name>school of arts Berlin</name> <address>123street</address> </school> </organisation> <teachers> <wo_number>34A</wo_number> <publication> <date>14-09-2018</date> <name>J. doe</name> </publication> <teacher id="A254"> <situation> <ill>no</ill> </situation> <situation> <ill>probable</ill> </situation> </teacher> <teacher id="B254"> <situation> <ill>probable</ill> </situation> </teacher> <teacher id="X92"> <situation> <ill>no</ill> </situation> <situation> <ill>probable</ill> </situation> </teacher> <teacher id="G56"> <situation> <ill>no</ill> </situation> </teacher> <teacher id="G56"> <situation> <ill>yes</ill> </situation> </teacher> </teachers> </root>
关键逻辑说明
- 前两个模板精准匹配到需要删除的
situation节点,而不是整个teacher,这样只会移除不符合要求的子节点,保留其他有效内容。 - 最后一个模板检查
teacher是否还存在situation子节点,如果没有则删除该空teacher,完全满足你的需求。
内容的提问来源于stack exchange,提问作者fasln01
相关产品推荐
相关产品推荐

