XSLT中如何选择<foo:bar>格式带命名空间前缀的XML节点?
问题原因分析
- 你遇到的
<foo:bar>格式的节点是命名空间限定的XML节点,冒号前的foo是命名空间前缀,冒号后的bar是本地节点名,前缀需要和一个固定的命名空间URI绑定后才能在XPath/XSLT中使用。 - 首次运行报错的原因:你的XSLT中没有声明与源XML匹配的
attribute命名空间,XPath解析器无法识别attribute:pa_brand中的前缀,所以抛出表达式求值失败的错误。 - 加单引号后无结果的原因:加单引号后节点名变成了字符串常量,相当于直接判断
'attribute:pa_brand' = 'bugatti',这个表达式永远为假,所以没有匹配结果。
修正方案
方案1:显式声明命名空间(推荐)
只需要在XSLT根节点xsl:stylesheet上补充源XML中用到的命名空间声明即可,修正后的完整XSLT代码如下:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:attribute="attribute" version="1.0"> <xsl:template match="/"> <Products> <xsl:apply-templates select="//Product[attribute:pa_brand = 'bugatti']"/> </Products> </xsl:template> <xsl:template match="Product"> <xsl:copy-of select="."/> </xsl:template> </xsl:stylesheet>
方案2:通过节点属性匹配(兼容场景)
如果不想显式声明命名空间前缀,或者前缀可能变化、只需要匹配本地名和命名空间URI的场景,可以用XPath的local-name()和namespace-uri()函数匹配:
<xsl:apply-templates select="//Product[*[local-name() = 'pa_brand' and namespace-uri() = 'attribute'] = 'bugatti']"/>
内容的提问来源于stack exchange,提问作者Marek Ivan
相关产品推荐
相关产品推荐

