当前位置: 首页 > news >正文

关于 xpath 查找 XML 元素的一点总结

测试环境

Win7 64

python 3.4.0

实践出真知

代码如下,更换不同的 xpath,和 response_to_check 进行测试

实验 1

xpath = ".//xmlns:return//xmlns:copeWith"

response_to_check = '' \

'<soap:Envelope xmlns="http://www.examp.com"

xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" >' \

' <node2>' \

' <id>goods1</id>' \

' </node2> ' \

' <ns1:Body

xmlns:ns1="http://service.rpt.data.platform.ddt.sf.com/">' \

' <ns2:selectByPrimaryKeyResponse

xmlns:ns2="http://service.rpt.data.platform.ddt.sf2.com/" ' \

' xmlns="http://www.overide_first_defaul_xmlns.com"> ' \

' <return>' \

' <copeWith>1.00</copeWith>' \

' <discount>0.99</discount>' \

' <id>144</id>' \

' <invoice>2</invoice>' \

' <invoiceType></invoiceType>' \

' <orderCode>DDT201704071952057186</orderCode>' \

' <orderDate>2017-04-07 19:52:06.0</orderDate>' \

' <paid>0.01</paid>' \

' <payType>pc</payType>' \

' <productName>快递包</productName>' \

' <state>0</state>' \

' <userId>2</userId>' \

' </return>' \

' <return>' \

' <copeWith>2.00</copeWith>' \

' <discount>0.99</discount>' \

' <id>143</id>' \

' <invoice>2</invoice>' \

' <invoiceType></invoiceType>' \

' <orderCode>DDT201704071951065731</orderCode>' \

' <orderDate>2017-04-07 19:51:07.0</orderDate> ' \

' <paid>0.01</paid>' \

' <payType>pc</payType>' \

' <productName>快递包</productName>' \

' <state>0</state>' \

' <userId>2</userId>' \

' </return>' \

' <return>' \

' <copeWith>3.00</copeWith>' \

' <discount>0.99</discount>' \

' <id>142</id>' \

' <invoice>2</invoice>' \

' <invoiceType></invoiceType>' \

' <orderCode>DDT201704071945408575</orderCode>' \

' <orderDate>2017-04-07 19:45:40.0</orderDate>' \

' <paid>0.01</paid>' \

' <payType>pc</payType>' \

' <productName>快递包</productName>' \

' <state>0</state>' \

' <userId>2</userId>' \

' </return> ' \

' <return attr="re">' \

' <copeWith>4.00</copeWith>' \

' <copeWith>5.00</copeWith>' \

' <discount>0.99</discount>' \

' <id>141</id>' \

' <invoice>1</invoice>' \

' <invoiceType>增值税普通发票</invoiceType>' \

' <orderCode>DDT201704071845403738</orderCode>' \

' <orderDate>2017-04-07 18:45:41.0</orderDate>' \

' <paid>0.01</paid>' \

' <productName>快递包</productName>' \

' <state>0</state>' \

' <userId attr="testattr">2</userId>' \

' </return>' \

' </ns2:selectByPrimaryKeyResponse>' \

' </ns1:Body>' \

' <ns1:Body

xmlns:ns1="http://service.rpt.data.platform.ddt.sf.com/">' \

' <ns2:selectByPrimaryKeyResponse

xmlns:ns2="http://service.rpt.data.platform.ddt.sf2.com/"> ' \

' </ns2:selectByPrimaryKeyResponse>' \

' <ns2:selectByPrimaryKeyResponse

xmlns:ns2="http://service.rpt.data.platform.ddt.sf2.com/"> ' \

' </ns2:selectByPrimaryKeyResponse>' \

' </ns1:Body>' \

'</soap:Envelope>'

root = ET.fromstring(response_to_check)

print(root)

if xpath == '.':

text_of_element = root.text

else:

xmlnsnamespace_dic = {} # 存放名称空间定义

print('正在获取 xmlns 定义')

match_result_list =re.findall('xmlns[^:]?=(.+?)[ |\>|\\\>]',

response_to_check, re.MULTILINE)

if match_result_list:

xmlns = match_result_list[len(match_result_list) - 1]

xmlns = xmlns.strip(' ')

xmlns = '{' + xmlns + '}'

print('xmlns 定义为:%s' % xmlns)

xmlnsnamespace_dic['xmlns'] = xmlns

print('正在获取"xmlns:xxx 名称空间定义')

match_result_list = re.findall('xmlns:(.+?)=(.+?)[ |>]',

response_to_check)

for ns in match_result_list:

xmlnsnamespace_dic[ns[0]] = '{' + ns[1] + '}'

print("最后获取的 prefix:uri 为:%s" % xmlnsnamespace_dic)

print('正在转换元素结点前缀')

for dic_key in xmlnsnamespace_dic.keys():

namespace = dic_key + ':'

if namespace in xpath:

uri = xmlnsnamespace_dic[dic_key]

xpath = xpath.replace(namespace, uri)

xpath = xpath.replace('"','')

print('转换后用于查找元素的 xpath%s' % xpath)

try:

elements_list = root.findall(xpath)

except Exception as e:

print('查找元素出错:%s' % e)

print('查找到的元素为:%s' % elements_list)

for element in elements_list:

text_of_element = element.text

print(text_of_element)

实验结果

以下为 xpath 设置不同值时的查找结果

/node

查找结果:报错,不能使用绝对路径

./node2

查找结果:找不到元素

./Body

查找结果:找不到元素

./ns1:Body/selectByPrimaryKeyResponse

查找结果:找不到元素

./ns1:Body/ns2:selectByPrimaryKeyResponse/return

查找结果:找不到元素

./ns1:Body/ns2:selectByPrimaryKeyResponse/xmlns:return[1]/copeWith

查找结果:找不到元素

-----------------------------

.

查找结果:根元素,即 Envelope 元素

ns1:Body

查找结果:所有名称空间为 ns1 的 Body 元素

./ns1:Body

查找结果:等同 ns1:Body

./ns1:Body/ns2:selectByPrimaryKeyResponse

查找结果:所有名称空间为 ns1 的 Body 元素下的所有名为 selectByPrimaryKeyResponse

的子元素

./ns1:Body/ns2:selectByPrimaryKeyResponse[2]

查找结果:所有名称空间为 ns1 的 Body 元素下,名称空间为 ns2 的第 2 个名为

selectByPrimaryKeyResponse 的子元素

./ns1:Body/ns2:selectByPrimaryKeyResponse/xmlns:return

查找结果:所有名称空间为 ns1 的 Body 元素下,所有名称空间为 ns2,名称为

selectByPrimaryKeyResponse 的子元素下,所有名称空间定义为

http://www.overide_first_defaul_xmlns.com 的 return 元素

./ns1:Body/ns2:selectByPrimaryKeyResponse/xmlns:return[1]/xmlns:copeWit

h

查找结果:所有名称空间为 ns1 的 Body 元素下,所有名称空间为 ns2,名称为

selectByPrimaryKeyResponse 的子元素下,第一个名称空间定义为

http://www.overide_first_defaul_xmlns.com 的 return 元素下,

名称空间定义为 http://www.overide_first_defaul_xmlns.com 的 copyWith 元素

.//xmlns:copeWith

查找结果:所有名称空间定义为 http://www.overide_first_defaul_xmlns.com 的

copeWith 元素

.//xmlns:copeWith[2]

查找结果:同一个元素节点下,名称空间定义为

http://www.overide_first_defaul_xmlns.com 的第二个 copeWith 元素(例中为

<copeWith>5.00</copeWith>' ,注意:这里的数字是针对兄弟节点的,下同,不再赘述)

# 注意:[]里面不支持 last()这种谓词,数字可以

.//xmlns:return//xmlns:copeWith"

查找结果:所有名称空间定义为 http://www.overide_first_defaul_xmlns.com 的

return 元素下,所有名称空间定义为 http://www.overide_first_defaul_xmlns.com

的 copeWith 元素

实验 2

对比实验 1,去掉 selectByPrimaryKeyResponse 元素中的 xmlns 定义:

xmlns="http://www.overide_first_defaul_xmlns.com"

xpath = ".//xmlns:return//xmlns:copeWith"

response_to_check = '' \

'<soap:Envelope xmlns="http://www.examp.com"

xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" >' \

' <node2>' \

' <id>goods1</id>' \

' </node2> ' \

' <ns1:Body

xmlns:ns1="http://service.rpt.data.platform.ddt.sf.com/">' \

' <ns2:selectByPrimaryKeyResponse

xmlns:ns2="http://service.rpt.data.platform.ddt.sf2.com/" ' \

' > ' \

' <return>' \

' <copeWith>1.00</copeWith>' \

' <discount>0.99</discount>' \

' <id>144</id>' \

' <invoice>2</invoice>' \

' <invoiceType></invoiceType>' \

' <orderCode>DDT201704071952057186</orderCode>' \

' <orderDate>2017-04-07 19:52:06.0</orderDate>' \

' <paid>0.01</paid>' \

' <payType>pc</payType>' \

' <productName>快递包</productName>' \

' <state>0</state>' \

' <userId>2</userId>' \

' </return>' \

' <return>' \

' <copeWith>2.00</copeWith>' \

' <discount>0.99</discount>' \

' <id>143</id>' \

' <invoice>2</invoice>' \

' <invoiceType></invoiceType>' \

' <orderCode>DDT201704071951065731</orderCode>' \

' <orderDate>2017-04-07 19:51:07.0</orderDate> ' \

' <paid>0.01</paid>' \

' <payType>pc</payType>' \

' <productName>快递包</productName>' \

' <state>0</state>' \

' <userId>2</userId>' \

' </return>' \

' <return>' \

' <copeWith>3.00</copeWith>' \

' <discount>0.99</discount>' \

' <id>142</id>' \

' <invoice>2</invoice>' \

' <invoiceType></invoiceType>' \

' <orderCode>DDT201704071945408575</orderCode>' \

' <orderDate>2017-04-07 19:45:40.0</orderDate>' \

' <paid>0.01</paid>' \

' <payType>pc</payType>' \

' <productName>快递包</productName>' \

' <state>0</state>' \

' <userId>2</userId>' \

' </return> ' \

' <return attr="re">' \

' <copeWith>4.00</copeWith>' \

' <copeWith>5.00</copeWith>' \

' <discount>0.99</discount>' \

' <id>141</id>' \

' <invoice>1</invoice>' \

' <invoiceType>增值税普通发票</invoiceType>' \

' <orderCode>DDT201704071845403738</orderCode>' \

' <orderDate>2017-04-07 18:45:41.0</orderDate>' \

' <paid>0.01</paid>' \

' <productName>快递包</productName>' \

' <state>0</state>' \

' <userId attr="testattr">2</userId>' \

' </return>' \

' </ns2:selectByPrimaryKeyResponse>' \

' </ns1:Body>' \

' <ns1:Body

xmlns:ns1="http://service.rpt.data.platform.ddt.sf.com/">' \

' <ns2:selectByPrimaryKeyResponse

xmlns:ns2="http://service.rpt.data.platform.ddt.sf2.com/"> ' \

' </ns2:selectByPrimaryKeyResponse>' \

' <ns2:selectByPrimaryKeyResponse

xmlns:ns2="http://service.rpt.data.platform.ddt.sf2.com/"> ' \

' </ns2:selectByPrimaryKeyResponse>' \

' </ns1:Body>' \ '</soap:Envelope>'

实验结果

.//xmlns:return//xmlns:copeWith

查找结果:所有名称空间定义为 http://www.examp.com 的 return 元素下,所有名称空

间定义为 http://www.examp.com 的 copeWith 元素

实验 3

xpath = "./xmlns:string"

response_to_check =''\

'<ArrayOfString

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"' \

' xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns="http://WebXml.com.cn/">' \

' <string>阿尔及利亚,3320</string>' \

' <string>阿根廷,3522</string>' \

' <string>阿曼,3170</string>' \

' <string>阿塞拜疆,3176</string>' \

' <string>埃及,3317</string>' \

' <string>埃塞俄比亚,3314</string>' \

' <string>爱尔兰,3246</string>' \

' <string>奥地利,3237</string>' \

' <string>澳大利亚,368</string>' \

' <string>巴基斯坦,3169</string>' \

' <string>巴西,3580</string>' \

' <string>保加利亚,3232</string>' \

' <string>比利时,3243</string>' \

'</ArrayOfString>'

实验结果:

./string

查找结果:找不到元素

./xmlns:string

查找结果:根元素下,所有名称空间定义为 xmlns 的 string 元素

实验 4

对比实验 3,去掉 xmlns=xmlns="http://WebXml.com.cn/

xpath = "./string"

response_to_check =''\

'<ArrayOfString

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"' \

' xmlns:xsd="http://www.w3.org/2001/XMLSchema">' \

' <string>阿尔及利亚,3320</string>' \

' <string>阿根廷,3522</string>' \

' <string>阿曼,3170</string>' \

' <string>阿塞拜疆,3176</string>' \

' <string>埃及,3317</string>' \

' <string>埃塞俄比亚,3314</string>' \

' <string>爱尔兰,3246</string>' \

' <string>奥地利,3237</string>' \

' <string>澳大利亚,368</string>' \

' <string>巴基斯坦,3169</string>' \

' <string>巴西,3580</string>' \

' <string>保加利亚,3232</string>' \

' <string>比利时,3243</string>' \

'</ArrayOfString>'

实验结果:

./string

查找结果:根元素下,所有名称空间定义为 http://WebXml.com.cn/的 string 元素

总结

1)xmlns=URI 定义元素默认的名称空间,使得作用范围内,可不用为元素显示设置名称空

间前缀。

<element_node xmlns=URI>

<node1>

...

<node2>

</element_node>

xmlns=URI 的作用域如下:

<element_node xmlns=URI>

作用域,也就是说,仅在元素范围内

</element>

2) 一份 xml 文档中,同时只能存在一个默认的 xmlns 名称空间,后续元素标签中定义的

xmlns 会自动导致前面定义的 xmlns 不可用

3)为元素设置自定义名称空间,形式如下:

<namespace:element_name xmlns:namespace=URI>

</namespace:element_name>

4)xpath 查找,不能使用绝对路径。

5)根据实验 1,实验 1&实验 2 对比,实验 3&实验 4 对比得出:

如果设置了 xmlns(默认名称空间 xmlns=xxxx,或者非默认的自定义名称空间

xmlns:prefix=URI),那么 xpath 查找名称空间作用域内的子元素时,必须使用名称空间

查找./xmlns:node_name、./prefix:node_name。

如果 xmlns 默认名称空间作用域范围内,子元素标签内设置了自定义名称空间,那么使用

自定义名称空间查找 ./…/prefix:node_name

如果既没定义默认名称空间,也没设置自定义名称空间,那么 xpath 查找元素时可不用指

定名称空间 ./node_name

 

http://www.xdnf.cn/news/111277.html

相关文章:

  • 2025新版懒人精灵零基础及各板块核心系统视频教程-全分辨率免ROOT自动化开发
  • Docker从0-1搭建个人云盘(支持Android iOS PC)
  • 关于Safari浏览器在ios<16.3版本不支持正则表达式零宽断言的解决办法
  • 汽车自动驾驶介绍
  • OpenHarmony 开源鸿蒙北向开发——hdc工具使用及常用命令(持续更新)
  • 数据库进阶之MySQL 程序
  • ARINC818协议一些说明综述
  • onlyoffice8.3.3发布了-豆豆容器市场同步更新ARM64版本
  • 【CAPL实战:以太网】对IPv4报文的Payload部分进行分片并创建分片包
  • 从Kafka读取数据
  • Cephalon端脑云:神经形态计算+边缘AI·重定义云端算力
  • Trae或者VsCode无法识别相对路径(不自动切换工作目录)
  • 高光谱相机在生物医学中的应用:病理分析、智慧中医与成分分析
  • React在什么情况下需要用useReducer
  • 前缀和-724.寻找数组的中心下标-力扣(LeetCode)
  • java—14 ZooKeeper
  • 【C++游戏引擎开发】第23篇:基础阴影映射(Shadow Mapping)
  • 2025/4/24
  • LeetCode 2799.统计完全子数组的数目:滑动窗口(哈希表)
  • 机器学习(9)——随机森林
  • 缓存与数据库数据一致性:旁路缓存、读写穿透和异步写入模式解析
  • “Daz to Unreal”将 G8 角色(包括表情)从 daz3d 导入到 UE5。在 UE5 中,我发现使用某个表情并与闭眼混合后,上眼睑出现了问题
  • 加密认证库openssl初始附带c/c++的使用源码
  • Nginx 中间件
  • 焊接机排错
  • 【C++指南】位运算知识详解
  • 直播预告 |【仓颉社区】第32期WORKSHOP
  • 蓝牙低功耗设备的漏洞与攻击——最新信息回顾
  • 图论算法体系:并查集、生成树、排序与路径搜索全解析
  • STM32F103系列单片机寄存器操作和标准库操作