试图用Python解析XML文件 - 我做错了什么?

问题描述:

我正在第一次使用XML和Python。最终目标是向REST服务发送请求,以XML接收响应,并根据返回的内容解析值并发送电子邮件。但是,REST服务还没有到位,所以现在我正在试验保存在我的C盘上的XML文件。试图用Python解析XML文件 - 我做错了什么?

我有一个简单的代码位,我很困惑,为什么它不工作。

这是我的XML文件( “XMLTest.xml”):

<Response> 
    <exitCode>1</exitCode> 
    <fileName>C:/Something/</fileName> 
    <errors> 
     <error>Error generating report</error> 
    </errors> 
</Response> 

这是我到目前为止的代码:

from xml.dom import minidom 

something = open("C:/XMLTest.xml") 
something = minidom.parse(something) 

nodeList = [] 
for node in something.getElementsByTagName("Response"): 
    nodeList.extend(t.nodeValue for t in node.childNodes) 
print nodeList 

但是打印出来的结果是...

[u'\n\t', None, u'\n\t', None, u'\n\t', None, u'\n'] 

我在做什么错?

我试图让该节点的值。有一个更好的方法吗? Python中是否有内置方法将xml文件转换为对象或字典?我想获得所有的价值,最好是附上名字。

+0

这就是我期望您发布的代码打印的代码。你想得到什么结果? – katrielalex 2010-08-26 14:41:28

+0

@Katrielalex - 我试图获取节点的值 - 1,“C:/ Something”等。我该如何实现?有没有更好的办法?有没有简单的方法来获得某种字典或对象的节点名称和值? – froadie 2010-08-26 14:45:16

+0

见下文。不幸的是,没有默认的方法将其转换为字典,因为XML太灵活了,因此没有明智的方法。你必须硬连接节点的索引(例如,如果有两个'exitCode'节点会发生什么?) – katrielalex 2010-08-26 14:53:09

这是否帮助?

doc = '''<Response> 
    <exitCode>1</exitCode> 
    <fileName>C:/Something/</fileName> 
    <errors> 
     <error>Error generating report</error> 
    </errors> 
</Response>''' 

from xml.dom import minidom 

something = minidom.parseString(doc) 

nodeList = [ ] 
for node in something.getElementsByTagName("Response"): 
    response = { } 
    response[ "exit code" ] = node.getElementsByTagName("exitCode")[ 0 ].childNodes[ 0 ].nodeValue 
    response[ "file name" ] = node.getElementsByTagName("fileName")[ 0 ].childNodes[ 0 ].nodeValue 
    errors = node.getElementsByTagName("errors")[ 0 ].getElementsByTagName("error") 
    response[ "errors" ] = [ error.childNodes[ 0 ].nodeValue for error in errors ] 

    nodeList.append(response) 

import pprint 
pprint.pprint(nodeList) 

产生

[{'errors': [u'Error generating report'], 
    'exit code': u'1', 
    'file name': u'C:/Something/'}] 
+0

这适用于这个特定的例子,但我在寻找一些更通用的东西,可以解析任何xml文件进入某种Python结构...... – froadie 2010-08-26 14:55:17

+1

@froadie:该函数已经存在;它被称为'xml.dom.minidom.parse'。没有可以充分表示XML的内置Python结构,所以它定义了它自己的结构。 – katrielalex 2010-08-26 14:59:01

+1

这是一个很好的解决方案。如果你想要更健壮的东西,你可能希望在xml.dom.minidom中使用'xml.etree.ElementTree',因为它往往涉及嵌套遍历的更少的语法。 – jathanism 2010-08-26 15:16:16

你不是想从DOM的角度来看,XML。即,'C:/ Something'不是标记名为'fileName'的元素的节点值;它是文本节点的nodevalue,它是标记名为'fileName'的元素的第一个子元素。

我建议你做的是在python本身中多玩一点:启动python。 ( ':/ < /文件名> > <响应> <文件名> C')

x.getElementsByTagName

从进口xml.dom的minidom命名

X = minidom.parseString

('Response') ... x.getElementsByTagName('Response')[0] .childNodes [0] ...

等等。您将快速了解文档如何被解析。

如果你是刚刚开始使用XML和Python,并没有令人信服的理由使用DOM,我强烈建议你看看ElementTree的API(在标准库中xml.etree.ElementTree实现)

举你一尝:

import xml.etree.cElementTree as etree 

tree = etree.parse('C:/XMLTest.xml') 
response = tree.getroot() 
exitcode = response.find('exitCode').text 
filename = response.find('fileName').text 
errors = [i.text for i in response.find('errors')] 

(如果你需要更多的权力 - 的XPath,验证,XSLT等等 - 你甚至可以切换到lxml,它实现了相同的API,但有很多群众演员)

我推荐我的l文库xml2obj。它比DOM更清洁。 “库”只有84行代码可以嵌入到任何地方。

In [185]: resp = xml2obj(something) 

In [186]: resp.exitCode 
Out[186]: u'1' 

In [187]: resp.fileName 
Out[187]: u'C:/Something/' 

In [188]: len(resp.errors) 
Out[188]: 1 

In [189]: for node in resp.errors: 
    .....:  print node.error 
    .....: 
    .....: 
Error generating report