1

我正在尝试使用 lxml 使用 python 解析 XML 文件,但在基本尝试时出错。我使用这篇文章lxml 教程来引导。

我的 XML 文件基本上是根据下面的记录构建的(我将其修剪下来以便于阅读):

<?xml version="1.0" ?>
<?xml-stylesheet href="file:///usr/share/nmap/nmap.xsl" type="text/xsl"?>
<nmaprun scanner="nmap" args="nmap -sV -p135,12345 -oX 10.232.0.0.16.xml 10.232.0.0/16" start="1340201347" startstr="Wed Jun 20 16:09:07 2012" version="5.21" xmloutputversion="1.03">
<host>
  <hostnames>
    <hostname name="host1.example.com" type="PTR"/>
  </hostnames>
</host>
</nmaprun>

我通过这个复杂的脚本运行它:

from lxml import etree

d = etree.parse("myfile.xml")
for host in d.findall("host"):
    aa = host.find("hostnames/hostname")
    print aa.attrib["name"]

AttributeError: 'NoneType' object has no attribute 'attrib'print线了。我检查了的值d,它们都被定义为元素。hostaa

如果这是显而易见的事情(很可能是),请提前道歉。

编辑:我按要求添加了 XML 文件的标题(我仍在阅读和重新阅读答案:))

谢谢!

4

3 回答 3

2

您可以使用 xpath 表达式解决此问题。

d.xpath('//hostname/@name') # thank you for comment

或者

for host in d.xpath('//hostname'):
    print host.get('name'), host.get('whatever else etc...')
于 2012-06-20T16:07:02.757 回答
1

尽管使用 XPath 会更有意义,但您的代码在单独运行时已经可以正常工作,只要处理主机未找到主机名的情况:

doc = lxml.etree.XML("""
  <nmaprun>
    <host>
      <hostnames>
        <hostname name="host1.example.com" type="PTR"/>
      </hostnames>
    </host>
  </nmaprun>""")
for host in doc.findall('host'):
  host_el = host.find('hostnames/hostname')
  if host_el is not None:
    print host_el.attrib['name']

使用 XPath(doc.xpath()而不是doc.find()or doc.findall()),可以做得更好,只过滤带有名称的主机名,从而完全避免错误记录:

  • host[hostnames/hostname/@name]将找到host至少hostnames有一个hostname带有 aaname属性的 s。
  • //hostnames/hostname/@name将直接只返回名称本身(如果使用lxml,则将它们公开为字符串)。
于 2012-06-20T16:18:23.700 回答
1

看起来您可能有一些<host>元素没有<hostnames>或没有<hostname>定义子元素。

正如@Charles Duffy 对您的问题的评论中所建议的那样,您需要检查您的调用是否find()找到了一个元素

for host in d.findall("host"):
    aa = host.find("hostnames/hostname")
    if aa:
        print aa.attrib["name"]
于 2012-06-20T16:21:48.610 回答