我尝试解析以下xml以提取某些数据,然后根据需要最终编辑数据。
这是xml:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<CHECKLIST>
<VULN>
<STIG_DATA>
<VULN_ATTRIBUTE>Vuln_Num</VULN_ATTRIBUTE>
<ATTRIBUTE_DATA>V-38438</ATTRIBUTE_DATA>
</STIG_DATA>
<STIG_DATA>
<VULN_ATTRIBUTE>Rule_Title</VULN_ATTRIBUTE>
<ATTRIBUTE_DATA>More text.</ATTRIBUTE_DATA>
</STIG_DATA>
<STIG_DATA>
<VULN_ATTRIBUTE>Vuln_Discuss</VULN_ATTRIBUTE>
<ATTRIBUTE_DATA>Some text here</ATTRIBUTE_DATA>
</STIG_DATA>
<STIG_DATA>
<VULN_ATTRIBUTE>IA_Controls</VULN_ATTRIBUTE>
<ATTRIBUTE_DATA></ATTRIBUTE_DATA>
</STIG_DATA>
<STIG_DATA>
<VULN_ATTRIBUTE>Rule_Ver</VULN_ATTRIBUTE>
<ATTRIBUTE_DATA>Gen000000</ATTRIBUTE_DATA>
</STIG_DATA>
<STATUS>NotAFinding</STATUS>
<FINDING_DETAILS></FINDING_DETAILS>
<COMMENTS></COMMENTS>
<SEVERITY_OVERRIDE></SEVERITY_OVERRIDE>
<SEVERITY_JUSTIFICATION></SEVERITY_JUSTIFICATION>
</VULN>
我想要从中获取的数据是直接跟随== Rule_Ver的VULN_ATTRIBUTE的STATUS,COMMENTS和ATTRIBUTE_DATA。所以在这个例子中。
我应该得到以下内容:
Gen000000 NotAFinding None
到目前为止,我可以轻松获得状态和注释,但无法找出ATTRIBUTE_DATA部分。我可以找到第一个(Vuln_Num),然后我尝试添加一个索引,但这会使&#34;列表索引超出范围&#34;错误。
这就是我现在所处的位置。
import xml.etree.ElementTree as ET
doc = ET.parse('test.ckl')
root=doc.getroot()
TagList = doc.findall("./VULN")
for curTag in TagList:
StatusTag = curTag.find("STATUS")
CommentTag = curTag.find("COMMENTS")
DataTag = curTag.find("./STIG_DATA/ATTRIBUTE_DATA")
print "GEN:[%s] Status:[%s] Comments: %s" %( DataTag.text, StatusTag.text, CommentTag.text)
这给出了以下输出:
GEN:[V-38438] Status:[NotAFinding] Comments: None
我想:
GEN:[Gen000000] Status:[NotAFinding] Comments: None
因此,最终目标是能够解析数百个并根据需要编辑注释字段。一旦我得到正确的元素,我就不会认为编辑部分会很难。
从逻辑上讲,我看到了两种方法。要么转到ATTRIBUTE_DATA [5]并抓取文本或找到VULN_ATTRIBUTE == Rule_Ver,然后抓住下一个ATTRIBUTE_DATA。
我试过这样做:
DataTag = curTag.find(".//STIG_DATA//ATTRIBUTE_DATA")[5]
and
DataTag [5] .text`
并且都给了我IndexError: list index out of range
我看到lxml有get_element_by_id和xpath,但是我无法将模块添加到这个系统中,所以它对我来说是非常的。
提前致谢。
答案 0 :(得分:2)
可以按位置找到元素,但是您使用了不正确的XPath语法。以下任何一行都应该有效:
DataTag = curTag.find("./STIG_DATA[5]/ATTRIBUTE_DATA") # Note: 5, not 4
DataTag = curTag.findall("./STIG_DATA/ATTRIBUTE_DATA")[4] # Note: 4, not 5
但是,我强烈建议不要使用它。无法保证Rule_Ver
STIG_DATA
实例始终是第五项。
如果您可以更改为lxml
,则可以:
DataTag = curTag.xpath(
'./STIG_DATA/VULN_ATTRIBUTE[text()="Rule_Ver"]/../ATTRIBUTE_DATA')[0]
由于您无法使用lxml
,因此您必须手动迭代STIG_DATA
元素,如下所示:
def GetData(curTag):
for stig in curTag.findall('STIG_DATA'):
if stig.find('VULN_ATTRIBUTE').text == 'Rule_Ver':
return stig.find('ATTRIBUTE_DATA')
这是一个完整的程序,其中添加了错误检查GetData()
:
import xml.etree.ElementTree as ET
doc = ET.parse('test.ckl')
root=doc.getroot()
TagList = doc.findall("./VULN")
def GetData(curTag):
for stig in curTag.findall('STIG_DATA'):
vuln = stig.find('VULN_ATTRIBUTE')
if vuln is not None and vuln.text == 'Rule_Ver':
data = stig.find('ATTRIBUTE_DATA')
return data
for curTag in TagList:
StatusTag = curTag.find("STATUS")
CommentTag = curTag.find("COMMENTS")
DataTag = GetData(curTag)
print "GEN:[%s] Status:[%s] Comments: %s" %( DataTag.text, StatusTag.text, CommentTag.text)
参考文献: