首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >iterparse无法解析字段,而其他类似的字段则可以

iterparse无法解析字段,而其他类似的字段则可以
EN

Stack Overflow用户
提问于 2013-02-03 16:39:02
回答 1查看 1.2K关注 0票数 2

我使用Python解析nessus扫描的iterparse结果(.nessus文件)。对于意外的记录,解析失败,尽管类似的记录已被正确解析。

XML文件的一般结构由许多如下所示的记录组成:

代码语言:javascript
复制
<ReportHost>
  <ReportItem>
    <foo>9.3</foo>
    <bar>hello</bar>
  </ReportItem>
  <ReportItem>
     <foo>10.0</foo>
     <bar>world</bar>
</ReportHost>
<ReportHost>
   ...
</ReportHost>

换句话说,很多主机(ReportHost)有很多项要报告(ReportItem),而后者有几个特征(foobar)。我将考虑为每个项目生成一行,以及它的特征。

在文件中间的简单一行(本例中为cvss_base_score)处解析失败

代码语言:javascript
复制
<cvss_base_score>9.3</cvss_base_score>

而大约200行类似的代码行已经被解析,没有出现问题。

相关的代码片段如下--它设置上下文标记(inReportHostinReportEvent,它们告诉我我在XML文件的结构中的什么位置,并根据上下文赋值或打印值)

代码语言:javascript
复制
import xml.etree.cElementTree as ET
inReportHost = False
inReportItem = False

for event, elem in ET.iterparse("test2.nessus", events=("start", "end")):
    if event == 'start' and elem.tag == "ReportHost":
        inReportHost = True
    if event == 'end' and elem.tag == "ReportHost":
        inReportHost = False
        elem.clear()
    if inReportHost:
        if event == 'start' and elem.tag == 'ReportItem':
            inReportItem = True
            cvss = ''
        if event == 'start' and inReportItem:
            if event == 'start' and elem.tag == 'cvss_base_score':
                cvss = elem.text
        if event == 'end' and elem.tag == 'ReportItem':
            print cvss
            inReportItem = False

cvss有时会有None值(在cvss = elem.text赋值之后),即使相同的条目在文件中之前已被正确解析。

如果我在赋值下面添加一些类似如下的内容

代码语言:javascript
复制
if cvss is None: cvss = "0"

然后,解析更多的cvss时会分配适当的值(有些则为空)。

当使用导致错误解析的<ReportHost>...</reportHost>并在程序中运行它时-它工作得很好(即。正如预期的那样,cvss被分配了9.3 )。

我在代码中的错误之处迷失了方向,因为有一大组相似的记录,有些是正确处理的,有些是不正确的(有些记录是相同的,但处理方式仍然是不同的)。我也找不到任何关于失败的记录的特别之处--早些时候和晚些时候完全相同的记录都可以。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-02-03 18:23:58

iterparse() docs

注意: iterparse()只保证它在发出“start”事件时看到了开始标记的“>”字符,所以属性是定义的,但文本和尾属性的内容在这一点上是未定义的。这同样适用于元素的子元素;它们可能存在,也可能不存在。如果您需要一个完全填充的元素,请改为查找“end”事件。

删除inReport*变量,并在完全解析"end“事件时仅处理ReportHost。使用ElementTree接口从当前的ReportHost元素中获取必要的信息,如cvss_base_score

要保留内存,请执行以下操作:

代码语言:javascript
复制
import xml.etree.cElementTree as etree

def getelements(filename_or_file, tag):
    context = iter(etree.iterparse(filename_or_file, events=('start', 'end')))
    _, root = next(context) # get root element
    for event, elem in context:
        if event == 'end' and elem.tag == tag:
            yield elem
            root.clear() # preserve memory

for host in getelements("test2.nessus", "ReportHost"):
    for cvss_el in host.iter("cvss_base_score"):
        print(cvss_el.text)
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14670792

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档