我正在尝试使用lxml使用python解析XML文件,但在基本尝试时出错。我使用this post和the 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
。
我检查了d
,host
和aa
的值,它们都被定义为元素。
如果这是显而易见的事情(可能是这样的话),请提前道歉。
编辑:我按要求添加了XML文件的标题(我还在阅读并重新阅读答案:))
谢谢!
答案 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]
会找到至少有host
个hostnames
且hostname
属性为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"]