Доступ к вложенным дочерним элементам в XML файле, проанализированном с помощью ElementTree

Я новичок в разборе XML. Этот XML файл имеет следующее дерево:

FHRSEstablishment
 |--> Header
 |    |--> ...
 |--> EstablishmentCollection
 |    |--> EstablishmentDetail
 |    |    |-->...
 |    |--> Scores
 |    |    |-->...
 |--> EstablishmentCollection
 |    |--> EstablishmentDetail
 |    |    |-->...
 |    |--> Scores
 |    |    |-->...

но когда я обращаюсь к нему через ElementTree и ищу теги и атрибуты child,

import xml.etree.ElementTree as ET
import urllib2
tree = ET.parse(
   file=urllib2.urlopen('http://ratings.food.gov.uk/OpenDataFiles/FHRS408en-GB.xml' % i))
root = tree.getroot()
for child in root:
   print child.tag, child.attrib

Я только получаю:

Header {}
EstablishmentCollection {}

что я предполагаю означает, что их атрибуты пусты. Почему это так, и как я могу получить доступ к детям, вложенным в EstablishmentDetail и Scores?

EDIT

Благодаря ответам ниже, я могу получить внутри дерева, но если я хочу получить значения, такие как в Scores, это терпит неудачу:

for node in root.find('.//EstablishmentDetail/Scores'):
    rating = node.attrib.get('Hygiene')
    print rating 

и производит

None
None
None

Почему это?

Ответ 1

Вам нужно выполнить iter() над вашим корнем.

то есть root.iter() сделает свое дело!

import xml.etree.ElementTree as ET
import urllib2
tree =ET.parse(urllib2.urlopen('http://ratings.food.gov.uk/OpenDataFiles/FHRS408en-GB.xml'))
root = tree.getroot()
for child in root.iter():
   print child.tag, child.attrib

Выход:

FHRSEstablishment {}
Header {}
ExtractDate {}
ItemCount {}
ReturnCode {}
EstablishmentCollection {}
EstablishmentDetail {}
FHRSID {}
LocalAuthorityBusinessID {}
...
  • Чтобы получить все теги внутри EstablishmentDetail, вам нужно найти этот тег, а затем просмотреть его дочерние элементы!

То есть, например.

for child in root.find('.//EstablishmentDetail'):
    print child.tag, child.attrib

Выход:

FHRSID {}
LocalAuthorityBusinessID {}
BusinessName {}
BusinessType {}
BusinessTypeID {}
RatingValue {}
RatingKey {}
RatingDate {}
LocalAuthorityCode {}
LocalAuthorityName {}
LocalAuthorityWebSite {}
LocalAuthorityEmailAddress {}
Scores {}
SchemeType {}
NewRatingPending {}
Geocode {}
  • Чтобы получить оценку для Hygiene, как вы упомянули в комментарии,

Что вы сделали, так это то, что при вызове for each in root.find('.//Scores'):rating=child.get('Hygiene') он получит первый тег Scores и будет иметь теги Hygiene, ConfidenceInManagement, Structural как дочерний. То есть очевидно, что все три ребенка не будут иметь элемент!

Вы должны сначала  - найти все теги Scores.  - найти Hygiene в каждом найденном теге!

for each in root.findall('.//Scores'):
    rating = each.find('.//Hygiene')
    print '' if rating is None else rating.text

Выход:

5
5
5
0
5

Ответ 2

Надеюсь, это может быть полезно:

import xml.etree.ElementTree as etree
with open('filename.xml') as tmpfile:
    doc = etree.iterparse(tmpfile, events=("start", "end"))
    doc = iter(doc)
    event, root = doc.next()
    num = 0
    for event, elem in doc:
        print event, elem