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

简介: Python 关于xpath查找XML元素的一点总结

关于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: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


目录
相关文章
|
6月前
|
XML 数据采集 存储
使用Java和XPath在XML文档中精准定位数据
在数据驱动的时代,从复杂结构中精确提取信息至关重要。XML被广泛用于数据存储与传输,而XPath则能高效地在这些文档中导航和提取数据。本文深入探讨如何使用Java和XPath精准定位XML文档中的数据,并通过小红书的实际案例进行分析。首先介绍了XML及其挑战,接着阐述了XPath的优势。然后,提出从大型XML文档中自动提取特定产品信息的需求,并通过代理IP技术、设置Cookie和User-Agent以及多线程技术来解决实际网络环境下的数据抓取问题。最后,提供了一个Java示例代码,演示如何集成这些技术以高效地从XML源中抓取数据。
238 7
使用Java和XPath在XML文档中精准定位数据
|
6月前
|
XML 前端开发 数据格式
三分钟搞定 Python XPath 语法
XPath(XML Path Language)是一种用于在 XML 文档中查找信息的语言。它基于树状结构的 XML 文档,可以通过路径表达式来选取节点或节点集。也常常用来解析 HTML。 如果你是一个前端,对用路径获取元素可能陌生又熟悉。陌生是很多的路径,熟悉的路径上又有熟悉的属性和方法。下面我们就来探究一下 XPath 的魅力。
|
3月前
|
XML 数据采集 数据格式
Python 爬虫必备杀器,xpath 解析 HTML
【11月更文挑战第17天】XPath 是一种用于在 XML 和 HTML 文档中定位节点的语言,通过路径表达式选取节点或节点集。它不仅适用于 XML,也广泛应用于 HTML 解析。基本语法包括标签名、属性、层级关系等的选择,如 `//p` 选择所有段落标签,`//a[@href=&#39;example.com&#39;]` 选择特定链接。在 Python 中,常用 lxml 库结合 XPath 进行网页数据抓取,支持高效解析与复杂信息提取。高级技巧涵盖轴的使用和函数应用,如 `contains()` 用于模糊匹配。
|
3月前
|
XML JSON API
如何使用Python将字典转换为XML
本文介绍了如何使用Python中的`xml.etree.ElementTree`库将字典数据结构转换为XML格式。通过定义递归函数处理字典到XML元素的转换,生成符合标准的XML文档,适用于与旧系统交互或需支持复杂文档结构的场景。示例代码展示了将一个简单字典转换为XML的具体实现过程。
31 1
|
4月前
|
存储 Python
Python:利用XML-RPC实现简单的远端过程调用
Python:利用XML-RPC实现简单的远端过程调用
26 1
|
4月前
|
数据采集 XML 数据格式
Python爬虫--xpath
Python爬虫--xpath
38 1
|
4月前
|
XML 数据库 数据格式
|
5月前
|
XML 数据格式 Python
python 解析xml遇到xml.etree.ElementTree.ParseError: not well-formed (invalid token): |4-8
python 解析xml遇到xml.etree.ElementTree.ParseError: not well-formed (invalid token): |4-8
|
5月前
|
Python
Python 选出列表中特定的元素
Python 选出列表中特定的元素
68 3
|
5月前
|
数据处理 索引 Python
Python列表与元素修改的操作技巧
Python列表提供了丰富的方法和技巧来进行高效的数据操作。熟练运用上述技巧,可以大大提高数据处理的效率和代码的可读性。实践中,根据具体需求灵活选择合适的方法,可以在保证代码效率的同时,也使代码更加简洁明了。
119 2

热门文章

最新文章