Python xml解析etree按位置查找元素X.

时间:2014-09-25 15:04:14

标签: python xml elementtree

我尝试解析以下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,但是我无法将模块添加到这个系统中,所以它对我来说是非常的。

提前致谢。

1 个答案:

答案 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)

参考文献: