python:基本XML解析错误(使用lxml)

时间:2012-06-20 16:01:38

标签: python xml xml-parsing

我正在尝试使用lxml使用python解析XML文件,但在基本尝试时出错。我使用this postthe lxml tutorials进行引导。

我的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。 我检查了dhostaa的值,它们都被定义为元素。

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

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

谢谢!

3 个答案:

答案 0 :(得分: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...')

答案 1 :(得分: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()doc.findall()),可以做得更好,仅过滤具有名称的主机名,从而完全避免错误记录:

  • host[hostnames/hostname/@name]会找到至少有hosthostnameshostname属性为name的{​​{1}}。
  • //hostnames/hostname/@name将直接仅返回名称本身(如果使用lxml,则将这些名称公开为字符串)。

答案 2 :(得分:1)

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

根据@Charles Duffy对您的问题的评论中的建议,您需要检查您对find()的调用是否找到了元素

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