[英]parsing xml find last element with matching attributes
我有一些寫得不好的xml,我試圖遍歷並提取每個測試的測試名稱,開始和結束時間。 我使用該數據將一列添加到csv。 我當前的實現檢查xml中的每個元素,而且似乎很慢。
這是一個xml示例
<ProcessStart Id="1" Type="MemTest" Name="WriteRead" Options=" /pi=5 /m=AA" Tick="1233" />
<ProcessStart Id="2" Type="MemTest" Name="WriteRead" Options=" /pi=5 /m=AA" Tick="1233" />
<ProcessStart Id="3" Type="MemTest" Name="WriteRead" Options=" /pi=5 /m=AA" Tick="1233" />
<ProcessEnd Id="1" Tick="7553"/>
<ProcessEnd Id="2" Tick="7553"/>
<ProcessEnd Id="3" Tick="7553"/>
<ProcessStart Id="17" Type="MemTest" Name="WriteRead" Options=" /pi=25 /m=AA" Tick="8126" />
<ProcessStart Id="18" Type="MemTest" Name="WriteRead" Options=" /pi=25 /m=AA" Tick="8127" />
<ProcessStart Id="19" Type="MemTest" Name="WriteRead" Options=" /pi=25 /m=AA" Tick="8127" />
<ProcessEnd Id="17" Tick="12873"/>
<ProcessEnd Id="18" Tick="12873"/>
<ProcessEnd Id="19" Tick="12873"/>
試圖弄清楚如何獲取與名稱和選項匹配的processStart的Id值。 到目前為止,我有:
root.find('ProcessStart[@Name="%s"][last()]' % test_name).get('Id')
但不是檢查與測試名稱匹配的最后一個元素,而是檢查processStart的最后一個元素。 我該如何解決? 還是提取此信息的最快方法是逐行讀取輸入文件?
新信息我想返回Id = 3的Id值。 這是存在所有具有匹配名稱和選項的ProcessStarts的最后一個值。 顯示的當前計數立即引用ProcessStart的最后一個實例,然后檢查名稱和選項條件。 我正在尋找一種找到具有匹配條件的最后一個ProcessStart的方法。
也許更好的例子是按選項進行匹配,因為此實例的名稱相同,因此:
options=" /pi=5 /m=AA"
test_id=root.find('ProcessStart[@Options="%s"][last()]' % options).get('Id')
使用此示例和該數據集,它將返回錯誤“ NoneType”對象沒有屬性“ get”,我相信這是因為最后一個元素與選項不匹配。 但是,我正在嘗試使用匹配選項來定位最后一個ProcessStart。
完整代碼:
import xml.etree.ElementTree as ET
#Read the xml file
tree = ET.parse('C:/Users/mkaminski/Desktop/sample.xml')
root = tree.getroot()
#get the first option
test_option=root.find('ProcessStart').get('Options')
test_id=root.find('ProcessStart[@Options="%s"][last()]' % test_option).get('Id')
完整的XML文件:
<AppLog App="RPx" Version="0.6.1" BaseVer="0.0.1" Time="20160208153547" Tick="0">
<RPxTest TestName="Tests/WriteRead" LongName="WriteRead_b=0_pi=5_m=AA_i=0" Instances="16" Memory="49534849024" Options=" /pi=5 /m=AA" IdRange="1-17" Tick="1233" />
<ProcessStart Id="1" Type="MemTest" Name="WriteRead" Options=" /pi=5 /m=AA" Tick="1233" />
<ProcessStart Id="2" Type="MemTest" Name="WriteRead" Options=" /pi=5 /m=AA" Tick="1233" />
<ProcessStart Id="3" Type="MemTest" Name="WriteRead" Options=" /pi=5 /m=AA" Tick="1233" />
<ProcessEnd Id="1" Tick="7553"/>
<ProcessEnd Id="2" Tick="7553"/>
<ProcessEnd Id="3" Tick="7553"/>
<RPxTest TestName="Tests/WriteRead" LongName="WriteRead_b=0_pi=25_m=AA_i=0" Instances="16" Memory="49534849024" Options=" /pi=25 /m=AA" IdRange="17-33" Tick="8126" />
<ProcessStart Id="17" Type="MemTest" Name="WriteRead" Options=" /pi=25 /m=AA" Tick="8126" />
<ProcessStart Id="18" Type="MemTest" Name="WriteRead" Options=" /pi=25 /m=AA" Tick="8127" />
<ProcessStart Id="19" Type="MemTest" Name="WriteRead" Options=" /pi=25 /m=AA" Tick="8127" />
<ProcessEnd Id="17" Tick="12873"/>
<ProcessEnd Id="18" Tick="12873"/>
<ProcessEnd Id="19" Tick="12873"/>
</AppLog>
錯誤:
File "C:/Anaconda3/Scripts/samle.py", line 9, in <module>
test_id=root.find('ProcessStart[@Options="%s"][last()]' % test_option).get('Id')
AttributeError: 'NoneType' object has no attribute 'get'
我認為您在ElementTree的xpath支持中遇到了限制(這是不完整的)。 使用lxml,您的命令可以完美運行。
要使用ElementTree進行此操作,請檢索所有匹配的元素,然后讓Python選擇最后一個。
更改
options=" /pi=5 /m=AA"
test_id=root.find('ProcessStart[@Options="%s"][last()]' % options).get('Id')
至
options=" /pi=5 /m=AA"
test_id=root.findall('ProcessStart[@Options="%s"]' % options)[-1].get('Id')
在此命令中,我們將按順序獲得所有匹配的ProcessStart元素作為列表,並僅獲取最后一個。 然后,我們可以獲取ID。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.