如何在XSLT中使用XPath检测XML自闭合标签
XSLT中能否检测自闭合标签?用XPath怎么实现?
首先明确:XSLT和XPath没法直接区分XML里的自闭合标签写法。因为XML解析器处理文档时,会把<entry/>这种自闭合标签,和<entry></entry>这种空的成对标签当成完全一样的空元素节点,解析后的DOM结构没有任何区别,所以XSLT/XPath根本看不到原始写法的差异。
如果你的实际需求是检测是否存在<entry>这个空元素节点(不管它是自闭合还是成对写的),那完全可以用XPath实现,下面针对你给的示例代码修正说明:
补全后的XML示例(原XML存在标签未闭合的语法错误)
<?xml version="1.0" encoding="UTF-8"?> <catalog> <cd> <title>1999 Grammy Nominees</title> <title>2000 Grammy Nominees</title> </cd> <cd> <entry/> <title>2010 Grammy Nominees</title> <title>2011 Grammy Nominees</title> </cd> </catalog>
修正后的XSLT代码(原代码存在语法错误和上下文匹配问题)
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <!-- 因用到fo:block元素,将输出模式改为XML,原text模式不适用 --> <xsl:output method="xml" indent="yes" /> <xsl:template match="/catalog"> <xsl:apply-templates/> </xsl:template> <!-- 匹配包含entry子节点的cd元素 --> <xsl:template match="cd[entry]"> <xsl:for-each select="title"> <fo:block background-color="blue"> <xsl:value-of select="."/> </fo:block> </xsl:for-each> </xsl:template> <!-- 匹配不包含entry子节点的cd元素 --> <xsl:template match="cd[not(entry)]"> <xsl:for-each select="title"> <fo:block background-color="red"> <xsl:value-of select="."/> </fo:block> </xsl:for-each> </xsl:template> </xsl:stylesheet>
关键逻辑说明
cd[entry]:直接匹配所有包含<entry>子节点的<cd>元素,不管<entry>是自闭合还是成对写法。cd[not(entry)]:匹配所有不包含<entry>子节点的<cd>元素。- 修正了原代码的语法问题:闭合了未结束的属性和标签,调整了
for-each的选择路径(当前上下文已是<cd>,直接选title即可,无需写cd/title)。
特殊情况补充
如果你真的需要区分自闭合标签和成对空标签的原始写法,常规XSLT/XPath做不到——因为XML解析器已经抹平了这种语法差异。这时需要用SAX这类基于事件的XML解析器,抓取原始标签事件来判断,但这已经超出了XSLT的处理范畴。
内容的提问来源于stack exchange,提问作者priyanka manogaran
相关产品推荐
相关产品推荐

