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

by:授客 QQ:1033553122

 

欢迎加入全国软件测试qq群:7156436

 

测试环境

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:copeWith

查找结果:所有名称空间为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

采用网盘链接分享,请点击链接查看:

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

Python 关于xpath查找XML元素的一点总结的更多相关文章

  1. 如何在python列表中查找某个元素的索引

    如何在python列表中查找某个元素的索引 2019-03-15 百度上回复别人的问题,几种方式的回答: 1) print('*'*15,'想找出里面有重复数据的索引值','*'*15) listA ...

  2. dom4j的xpath查找xml的指定节点

    递归遍历所有节点http://blog.csdn.net/sidihuo/article/details/47318723 获取Document SAXReader saxReader = new S ...

  3. Python笔记(二)查找重复元素

    一.查找数列重复元素---count() >>> list = [,,,,,,,,,,,] >>> set = set(list) >>> for ...

  4. Python通过xpath查找元素通过selenium读取元素信息

    #coding:utf-8 from selenium import webdriver import time url ='http://www.baidu.com' driver = webdri ...

  5. C#使用xpath查找xml节点信息

    Xpath是功能很强大的,但是也是相对比较复杂的一门技术,最好还是到博客园上面去专门找一些专业的帖子来看一看,下面是一些简单的Xpath语法和一个实例,提供给你参考一下. xml示例: <?xm ...

  6. Python列表中查找某个元素的索引(多个)

    enumerate() 函数用于将一个可遍历的数据对象(如列表.元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中. 以下是 enumerate() 方法的语法: e ...

  7. 用XPath查找HTML节点或元素

    更新版以后会在我的新博客更新,请您移步 https://blog.clso.fun/posts/2019-03-03/46.html 虽然JQ和JS都能很方便的查找包含了ID及类名的元素,但某些情况下 ...

  8. Xml中SelectSingleNode方法,xpath查找某节点用法

    Xml中SelectSingleNode方法,xpath查找某节点用法 最常见的XML数据类型有:Element, Attribute,Comment, Text. Element, 指形如<N ...

  9. 30天C#基础巩固----查找XML文件元素

    一:XML文档 了解xml文档. 利用代码来创建XML文档. //引用命名空间+using System.Xml; XmlDocument xdoc=new XmlDocument(); XmlDec ...

随机推荐

  1. flash中调用XML遇到的中文显示异常问题

    昨天使用flash调用XML文件进行显示时,出现了中文无法显示的问题,记录一下解决方法: 1.字体设置: 一般flash里的动态文本和嵌入文本都是默认的使用Arial字体,这个字体里可能没有中文,所以 ...

  2. H5在WebView上开发小结

    背景 来自我司业务方要求,需开发一款APP.但由于时间限制,只能采取套壳app方式,即原生app内嵌webview展示前端页面.本文主要记述JavaScript与原生app间通信,以及内嵌webvie ...

  3. 《CLR Via C#》读书笔记:24.运行时序列化

    一.什么是运行时序列化 序列化的作用就是将对象图(特定时间点的对象连接图)转换为字节流,这样这些对象图就可以在文件系统/网络进行传输. 二.序列化/反序列化快速入门 一般来说我们通过 FCL 提供的 ...

  4. vue 关于图片路径的问题

    在vue 中,当我们想加载assets中的图片,本人按照多年的开发经验会这样写,那是没问题的 <img src="../assets.1.jpg"/> 如果我要用v-b ...

  5. jsp fmt页面显示value does not support runtime expressions

    最近使用Struts2+Spring3+Mybatis3做一个项目,在用户修改页面显示生日, <fmt:formatDate value="${user.birthday}" ...

  6. Spring boot @EnableScheduling 和 @Scheduled 注解使用例子

    前言 Spring Boot提供了@EnableScheduling和@Scheduled注解,用于支持定时任务的执行,那么接下来就让我们学习下如何使用吧: 假设我们需要每隔10秒执行一个任务,那么我 ...

  7. 【原创】深入理解c++的右值引用

    0 左值和右值     一个左值表达式代表的是对象本身,而右值表达式代表的是对象的值:变量也是左值.   1 右值引用作用 为了支持移动操作(包括移动构造函数和移动赋值函数),C++才引入了一种新的引 ...

  8. 流式大数据计算实践(1)----Hadoop单机模式

    一.前言 1.从今天开始进行流式大数据计算的实践之路,需要完成一个车辆实时热力图 2.技术选型:HBase作为数据仓库,Storm作为流式计算框架,ECharts作为热力图的展示 3.计划使用两台虚拟 ...

  9. MyBatis源码解析(十一)——Parsing解析模块之通用标记解析器(GenericTokenParser)与标记处理器(TokenHandler)

    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6724223.html 1.回顾 上面的几篇解析了类型模块,在MyBatis中类型模块包含的 ...

  10. #20 Python文件

    前言 前面几节枯燥的模块终于结束了,想要完全掌握前几节的模块需要不断的练习才行,毕竟眼过千遍不如手过一遍嘛.在一些项目需求里,要对文件进行IO操作,毕竟重要数据不可能打印到屏幕上而不去保存,Pytho ...