我在XML中有很多行,我试图获得一个特定节点属性的实例。
<foo>
<bar>
<type foobar="1"/>
<type foobar="2"/>
</bar>
</foo>
我如何访问属性foobar的值?在这个例子中,我想要“1”和“2”。
我在XML中有很多行,我试图获得一个特定节点属性的实例。
<foo>
<bar>
<type foobar="1"/>
<type foobar="2"/>
</bar>
</foo>
我如何访问属性foobar的值?在这个例子中,我想要“1”和“2”。
当前回答
为了简单起见,我建议使用xmltodict。
它将XML解析为OrderedDict;
>>> e = '<foo>
<bar>
<type foobar="1"/>
<type foobar="2"/>
</bar>
</foo> '
>>> import xmltodict
>>> result = xmltodict.parse(e)
>>> result
OrderedDict([(u'foo', OrderedDict([(u'bar', OrderedDict([(u'type', [OrderedDict([(u'@foobar', u'1')]), OrderedDict([(u'@foobar', u'2')])])]))]))])
>>> result['foo']
OrderedDict([(u'bar', OrderedDict([(u'type', [OrderedDict([(u'@foobar', u'1')]), OrderedDict([(u'@foobar', u'2')])])]))])
>>> result['foo']['bar']
OrderedDict([(u'type', [OrderedDict([(u'@foobar', u'1')]), OrderedDict([(u'@foobar', u'2')])])])
其他回答
如果你使用python-benedict,就不需要使用lib特定的API。只需从XML初始化一个新实例并轻松管理它,因为它是dict子类。
安装很简单:pip install python-benedict
from benedict import benedict as bdict
# data-source can be an url, a filepath or data-string (as in this example)
data_source = """
<foo>
<bar>
<type foobar="1"/>
<type foobar="2"/>
</bar>
</foo>"""
data = bdict.from_xml(data_source)
t_list = data['foo.bar'] # yes, keypath supported
for t in t_list:
print(t['@foobar'])
它支持并规范化多种格式的I/O操作:Base64, CSV, JSON, TOML, XML, YAML和查询字符串。
它在GitHub上经过了很好的测试和开源。披露:我是作者。
我很受伤,没有人建议熊猫。Pandas有一个read_xml()函数,它非常适合这种扁平的xml结构。
import pandas as pd
xml = """<foo>
<bar>
<type foobar="1"/>
<type foobar="2"/>
</bar>
</foo>"""
df = pd.read_xml(xml, xpath=".//type")
print(df)
输出:
foobar
0 1
1 2
你可以使用BeautifulSoup:
from bs4 import BeautifulSoup
x="""<foo>
<bar>
<type foobar="1"/>
<type foobar="2"/>
</bar>
</foo>"""
y=BeautifulSoup(x)
>>> y.foo.bar.type["foobar"]
u'1'
>>> y.foo.bar.findAll("type")
[<type foobar="1"></type>, <type foobar="2"></type>]
>>> y.foo.bar.findAll("type")[0]["foobar"]
u'1'
>>> y.foo.bar.findAll("type")[1]["foobar"]
u'2'
#If the xml is in the form of a string as shown below then
from lxml import etree, objectify
'''sample xml as a string with a name space {http://xmlns.abc.com}'''
message =b'<?xml version="1.0" encoding="UTF-8"?>\r\n<pa:Process xmlns:pa="http://xmlns.abc.com">\r\n\t<pa:firsttag>SAMPLE</pa:firsttag></pa:Process>\r\n' # this is a sample xml which is a string
print('************message coversion and parsing starts*************')
message=message.decode('utf-8')
message=message.replace('<?xml version="1.0" encoding="UTF-8"?>\r\n','') #replace is used to remove unwanted strings from the 'message'
message=message.replace('pa:Process>\r\n','pa:Process>')
print (message)
print ('******Parsing starts*************')
parser = etree.XMLParser(remove_blank_text=True) #the name space is removed here
root = etree.fromstring(message, parser) #parsing of xml happens here
print ('******Parsing completed************')
dict={}
for child in root: # parsed xml is iterated using a for loop and values are stored in a dictionary
print(child.tag,child.text)
print('****Derving from xml tree*****')
if child.tag =="{http://xmlns.abc.com}firsttag":
dict["FIRST_TAG"]=child.text
print(dict)
### output
'''************message coversion and parsing starts*************
<pa:Process xmlns:pa="http://xmlns.abc.com">
<pa:firsttag>SAMPLE</pa:firsttag></pa:Process>
******Parsing starts*************
******Parsing completed************
{http://xmlns.abc.com}firsttag SAMPLE
****Derving from xml tree*****
{'FIRST_TAG': 'SAMPLE'}'''
simplified_scrapy:一个新的库,我使用后就爱上了它。我向你推荐。
from simplified_scrapy import SimplifiedDoc
xml = '''
<foo>
<bar>
<type foobar="1"/>
<type foobar="2"/>
</bar>
</foo>
'''
doc = SimplifiedDoc(xml)
types = doc.selects('bar>type')
print (len(types)) # 2
print (types.foobar) # ['1', '2']
print (doc.selects('bar>type>foobar()')) # ['1', '2']
这里有更多的例子。这个库很容易使用。