2012-06-20 43 views
1

我想用python使用lxml解析XML文件,但在基本尝试中得到一个错误。我使用this postthe lxml tutorials来引导。python:与基本的XML解析错误(使用lxml)

我的XML文件基本上是从下面记录内置(我修剪下来,使其更易于阅读):

from lxml import etree 

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

我:

<?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> 

我通过这个复杂的脚本运行在print行上获得AttributeError: 'NoneType' object has no attribute 'attrib'。 我检查了d,hostaa的值,它们都被定义为元素。

如果这是明显的事情(可能是),我们会表示歉意。

编辑:我加入了XML文件的文件头的要求(我仍然读和重读的答案:))

谢谢!

+2

有'aa'是'NoneType'意味着'find' WASN无法找到任何东西。因此,这与XML特定代码中的错误*不同,因为它是(1)稍微错误的搜索,以及(2)在处理lxml库的_output时缺少错误检查。 –

+0

另外 - 当你说“根据下面的记录构建”时,我认为这意味着你将把事情抛出去;即。有一个根,一个标题,&c。你没有透露。这些东西很重要;请确保您至少告诉我们您的文档的根源是什么样子。 –

+0

@Charles Duffy:对不起,我更新了XML文件。发现是成功的(从没有返回错误的意义上说,唯一的错误就是在打印中)。当打印“aa”时,我得到一堆与文件相匹配的元素,它是不工作的属性部分。 – WoJ

回答

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 S的有与具有一个name属性的hostname至少一个hostnames
  • //hostnames/hostname/@name将直接返回名称本身(如果使用lxml,将它们暴露为字符串)。
+0

问题中的XML没有''作为根元素。 – mzjn

+0

@mzjn他清楚地将他的XML文件描述为“从下面的记录构建”,它不同于仅包含下面的记录。 “包含”给定记录的文件当然可以有一个未公开的根元素。 –

+0

@mzjn:我更新了XML文件 – WoJ

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

其实,'// hostname/@ name'。 –

+0

@larsmans ...好吧,Jon的解决方案是正确的,如果我们仍然希望下面的行能够做一个attrib查找,但是,直接去字符串(并且完全删除变量赋值)更有意义。 –

+0

Okies,谢谢你的提问@larsmans –

1

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

如由@Charles达菲你的问题中留言建议,你需要检查你到find()呼叫发现的元素

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