我有一个简单的文件XML,如下所示:
<brandName type="http://example.com/codes/bmw#" abbrev="BMW" value="BMW" />BMW</brandName>
<maxspeed>
<value>250</value>
<unit type="http://example.com/codes/units#" value="miles per hour" abbrev="mph" />
</maxspeed>
我想使用lxml解析它并获取它的值: 使用brandName,它只需要:
'brand_name' : m.findtext(NS+'brandName')
如果我想进入它的abbrev属性。
'brand_name' : m.findtext(NS+'brandName').attrib['abbrev']
使用maxspeed,我可以得到maxspeed的值:
'maxspeed_value' : m.findtext(NS+'maxspeed/value'),
或:
'maxspeed_value' : m.find(NS+'maxspeed/value').text,
现在,我想获得单位内部的属性,我尝试了很多不同的方式,但我失败了。大部分时间的错误是:
'NoneType' object has no attribute 'attrib'
以下是我尝试过的几种方法,但失败了:
'maxspeed_unit' : m.find(NS+'maxspeed/value').attrib['abbrev'],
'maxspeed_unit' : (m.find(NS+'maxspeed/value'))get('abbrev'),
你能不能给我一些暗示为什么它不起作用? 非常感谢你!
更新XML:
<Car xmlns="http://example.com/vocab/xml/cars#">
<dateStarted>2011-02-05</dateStarted>
<dateSold>2011-02-13</dateSold>
<name type="http://example.com/codes/bmw#" abbrev="X6" value="BMW X6" >BMW X6</name>
<brandName type="http://example.com/codes/bmw#" abbrev="BMW" value="BMW" />BMW</brandName>
<maxspeed>
<value>250</value>
<unit type="http://example.com/codes/units#" value="miles per hour" abbrev="mph" />
</maxspeed>
<route type="http://example.com/codes/routes#" abbrev="HW" value="Highway" >Highway</route>
<power>
<value>180</value>
<unit type="http://example.com/codes/units#" value="powerhorse" abbrev="ph" />
</power>
<frequency type="http://example.com/codes/frequency#" value="daily" >Daily</frequency>
</Car>
答案 0 :(得分:0)
import lxml.etree as ET
content='''
<Car xmlns="http://example.com/vocab/xml/cars#">
<brandName type="http://example.com/codes/bmw#" abbrev="BMW" value="BMW" >BMW</brandName>
<maxspeed>
<value>250</value>
<unit type="http://example.com/codes/units#" value="miles per hour" abbrev="mph" />
</maxspeed>
</Car>
'''
doc=ET.fromstring(content)
NS = 'http://example.com/vocab/xml/cars#'
# print(ET.tostring(doc,pretty_print=True))
for x in doc.xpath('//ns:maxspeed/ns:unit/@abbrev',namespaces={'ns': NS}):
print(x)
产量
mph
答案 1 :(得分:0)
lxml元素上的.find方法只搜索该元素的直接子子元素。例如,在这个xml中:
<root>
<brandName type="http://example.com/codes/bmw#" abbrev="BMW" value="BMW">BMW</brandName>
<maxspeed>
<value>250</value>
<unit type="http://example.com/codes/units#" value="miles per hour" abbrev="mph" />
</maxspeed>
</root>
您可以使用根元素.find方法来定位brandname元素或maxspeed元素,但搜索不会遍历这些内部元素。
所以你可以这样做:
root.find('maxspeed').find('unit') #returns the unit Element
从这个返回的元素中,您可以访问属性。
如果您要搜索XML文档中的所有元素,可以使用.iter()方法。因此,对于前面的示例,您可以说:
for element in root.iter(tag='unit'):
print element #This would print all the unit elements in the document.
编辑:以下是使用您提供的xml的一个小功能完整的示例:
import lxml.etree
from StringIO import StringIO
def ns_join(element, tag, namespace=None):
'''Joins the namespace and tag together, and
returns the fully qualified name.
@param element - The lxml.etree._Element you're searching
@param tag - The tag you're joining
@param namespace - (optional) The Namespace shortname default is None'''
return '{%s}%s' % (element.nsmap[namespace], tag)
def parse_car(element):
'''Parse a car element, This will return a dictionary containing
brand_name, maxspeed_value, and maxspeed_unit'''
maxspeed = element.find(ns_join(element,'maxspeed'))
return {
'brand_name' : element.findtext(ns_join(element,'brandName')),
'maxspeed_value' : maxspeed.findtext(ns_join(maxspeed,'value')),
'maxspeed_unit' : maxspeed.find(ns_join(maxspeed, 'unit')).attrib['abbrev']
}
#Create the StringIO object to feed to the parser.
XML = StringIO('''
<Reports>
<Car xmlns="http://example.com/vocab/xml/cars#">
<dateStarted>2011-02-05</dateStarted>
<dateSold>2011-02-13</dateSold>
<name type="http://example.com/codes/bmw#" abbrev="X6" value="BMW X6" >BMW X6</name>
<brandName type="http://example.com/codes/bmw#" abbrev="BMW" value="BMW" >BMW</brandName>
<maxspeed>
<value>250</value>
<unit type="http://example.com/codes/units#" value="miles per hour" abbrev="mph" />
</maxspeed>
<route type="http://example.com/codes/routes#" abbrev="HW" value="Highway" >Highway</route>
<power>
<value>180</value>
<unit type="http://example.com/codes/units#" value="powerhorse" abbrev="ph" />
</power>
<frequency type="http://example.com/codes/frequency#" value="daily" >Daily</frequency>
</Car>
</Reports>
''')
#Get the root element object of the xml
car_root_element = lxml.etree.parse(XML).getroot()
# For each 'Car' tag in the root element,
# we want to parse it and save the list as cars
cars = [ parse_car(element)
for element in car_root_element.iter() if element.tag.endswith('Car')]
print cars
希望它有所帮助。