【发布时间】:2016-02-13 04:58:29
【问题描述】:
我有一些写得很糟糕的 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 值。这是所有具有匹配名称和选项的 ProcessStart 都存在的最后一个值。显示的当前计数立即引用 ProcessStart 的最后一个实例,然后检查名称和选项条件。我正在寻找一种方法来找到具有匹配条件的最后一个 ProcessStart。
也许一个更好的例子是按选项匹配,因为这个实例的名称是相同的,所以:
options=" /pi=5 /m=AA"
test_id=root.find('ProcessStart[@Options="%s"][last()]' % options).get('Id')
使用这个例子和这个数据集,它会返回一个错误'NoneType' object has no attribute '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'
【问题讨论】:
-
请展示一个完整但最小的输入文档样本以及所有必要的(这意味着,只有必要的)Python 代码来重现您的问题。求助:stackoverflow.com/help/mcve.
-
你的命令看起来不错。它返回了什么,你希望它返回什么?如果你想获取 ID 更改
.get('Tick')到.get('Id')。 -
MathiasMüller 重复该 xml 格式以创建一个大的 xml 文件。该示例应该显示我正在尝试完成的工作。 @Matthew 太长,无法添加在编辑中添加的评论
-
“该示例应该显示我想要完成的任务” - 不,它没有。展示一个小而完整的输入 XML 示例,以及所有必要的 Python 代码(正如我已经告诉过您的那样)。然后,显示运行此 Python 代码所期望的确切输出。
-
@MathiasMüller 来了
标签: python xml parsing xpath python-3.4