namespace-uri()函数用于获取节点的命名空间uri,若节点无命名空间则返回空字符串;在xpath中使用时需结合节点定位,如namespace-uri(.)或namespace-uri(元素名),并注意命名空间声明、继承与编程语言中的前缀映射配置,否则可能导致匹配失败。

namespace-uri()
要使用
namespace-uri()
namespace-uri(.)
namespace-uri(element_name)
namespace-uri(@attribute_name)
我们来看个例子,这样会更直观:
假设我们有这么一段XML:
<数据根 xmlns="http://example.com/默认命名空间">
<子节点 xmlns:我的前缀="http://example.com/我的命名空间">
<我的前缀:项目 id="123" xmlns:次级前缀="http://example.com/次级命名空间">
<次级前缀:详情>一些细节内容</次级前缀:详情>
</我的前缀:项目>
<普通子节点>又一个</普通子节点>
</子节点>
<另一个子节点>
<无前缀子节点 xmlns="http://example.com/新的默认命名空间"/>
</另一个子节点>
</数据根>现在,我们用
namespace-uri()
<数据根>
namespace-uri(/数据根)
http://example.com/默认命名空间
<子节点>
namespace-uri(/数据根/子节点)
http://example.com/默认命名空间
<我的前缀:项目>
namespace-uri(/数据根/子节点/我的前缀:项目)
http://example.com/我的命名空间
<次级前缀:详情>
namespace-uri(/数据根/子节点/我的前缀:项目/次级前缀:详情)
http://example.com/次级命名空间
id
namespace-uri(/数据根/子节点/我的前缀:项目/@id)
""
<普通子节点>
namespace-uri(/数据根/子节点/普通子节点)
http://example.com/默认命名空间
<数据根>
<无前缀子节点>
namespace-uri(/数据根/另一个子节点/无前缀子节点)
http://example.com/新的默认命名空间
在我处理XML和XPath的这些年里,命名空间绝对是让人最头疼但也最容易忽视的一个点。我发现有几个坑是大家特别容易踩的:
默认命名空间的问题:这是个大头。XML文档里可以有个默认命名空间,比如
xmlns="http://some.uri"
<book>
//book
bk
//bk:book
属性命名空间:一个常见的误解是,如果一个元素有命名空间,它的属性也跟着有。其实不是。绝大多数属性是没有命名空间的,即使它们所在的元素有。
namespace-uri()
命名空间的继承与覆盖:命名空间是会继承的,但它也可以在子元素上被“覆盖”或重新声明。理解这个机制非常重要。一个元素声明的命名空间,对它自己和它的所有子孙元素都有效,除非某个子孙元素自己又声明了一个新的命名空间,那个新的声明就会覆盖掉继承来的。我经常看到有人因为没搞清楚这个继承链,导致XPath路径写错了。
XPath处理器配置:这更偏向于编程层面。无论你用Python、Java还是其他语言的XPath库,它们通常都需要你显式地告诉它们:“嘿,这个
ns
http://my.namespace.com
这几乎百分之九十九是因为你没有正确地处理命名空间。XPath,特别是广泛使用的XPath 1.0,对命名空间的要求非常严格。它不会“猜测”你想要什么。
一个非常典型的场景就是:
你的XML长这样:
<数据 xmlns="http://我的数据.com/命名空间">
<条目>第一项</条目>
</数据>然后你尝试用
//条目
<条目>
http://我的数据.com/命名空间
要解决这个问题,你需要做的是:
mydata
http://我的数据.com/命名空间
//mydata:条目
举个Python
lxml
from lxml import etree
xml_str = '<数据 xmlns="http://我的数据.com/命名空间"><条目>你好</条目></数据>'
root = etree.fromstring(xml_str)
# 错误示范:直接匹配会失败
# print(root.xpath('//条目')) # 结果是 []
# 正确示范:定义命名空间映射,并在XPath中使用
ns_map = {'mydata': 'http://我的数据.com/命名空间'}
# print(root.xpath('//mydata:条目', namespaces=ns_map)[0].text) # 结果是 '你好'你看,只是多了一个
namespaces
另一个情况是前缀与URI不匹配。你可能定义了前缀,但它对应的URI和XML文档中元素的实际命名空间URI不一致。记住,前缀本身只是一个本地的别名,真正重要的是它映射到的那个URI。
我的前缀:项目
我的前缀
http://example.com/我的命名空间
最后,属性命名空间被误解。我再强调一下,除非属性本身有
xmlns:
xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="..."
id="123"
ns:id
@id
namespace-uri(@id)
实际开发中,我们很少直接在命令行里跑XPath,更多的是通过编程语言的库来操作。这里我拿Python和Java举例,它们是比较常用的:
Python (lxml 库)
lxml
from lxml import etree
xml_doc = """
<根元素 xmlns="http://默认命名空间.com/ns" xmlns:前缀="http://带前缀命名空间.com/ns">
<前缀:特定元素>
<子元素>内部文本</子元素>
</前缀:特定元素>
<另一个元素 />
</根元素>
"""
root = etree.fromstring(xml_doc)
# 定义命名空间映射。即使是XML中的默认命名空间,
# 在lxml的XPath表达式中也需要为其指定一个前缀。
ns_map = {
'd': 'http://默认命名空间.com/ns', # 'd' 代表默认命名空间
'p': 'http://带前缀命名空间.com/ns' # 'p' 代表带前缀的命名空间
}
# 获取 <前缀:特定以上就是XPath的namespace-uri()函数怎么获取命名空间?的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号