Python 關於xpath查找XML元素的一點總結


關於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


 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM