local-name()返回节点本地名称(冒号后部分),忽略前缀和命名空间;name()返回源文档中带前缀的完整名称(若存在前缀),否则返回本地名。前者适用于跨命名空间匹配,后者多用于调试。
当XML文档使用命名空间时,local-name() 和 name() 的行为差异很关键:前者只返回元素或属性的本地名称(去掉前缀和命名空间),后者返回带前缀的完整名称(如果存在前缀)或无前缀的名称(如果没声明前缀)。
local-name() 总是返回节点的本地部分(local part),也就是冒号 : 后面那一段,没有前缀、没有URI、不依赖上下文绑定。即使节点属于某个命名空间,它也完全忽略。
,local-name(/ns:book) → "book"
(默认命名空间),local-name(/book) → "book"(依然有效),local-name(@id) → "id"
name() 返回的是节点在源文档中实际使用的名称形式——包括前缀(如果写了),但不包含命名空间URI。它的结果取决于解析器是否保留了前缀绑定,以及节点是否显式用了前缀。
,name(/ns:book) → "ns:book"(前提是解析器保留了 ns 前缀)(默认命名空间,无前缀),name(/book) → "book"(没前缀,所以就是本地名)name() 也可能返回 "book",而非 "ns:book"
因为真实XML中,前缀是任意的(ns、abc、my 都可能映射同一URI),而本地名才是语义核心。用 local-name() 可以安全地写不依赖前缀的表达式:
book 元素://*[local-name()='book']
name()='ns:book' 很脆弱——换一个前缀就失效name() 主要价值在于观察原始文档结构,比如检查某个节点是否用了特定前缀,或区分同名但不同前缀的元素(虽然少见)。生产级XPath一般避免依赖它做逻辑判断,除非你明确
控制输入格式且前缀固定。
基本上就这些。记住一个口诀:local-name 看“是什么”,name 看“怎么叫”——而 XML 的本质意义在“是什么”。