簡體   English   中英

解析xml查找具有匹配屬性的最后一個元素

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM