2014-02-03 2 views
4

У меня есть дерево XML, которое я бы хотел проанализировать с помощью Elementtree. Мой XML выглядит какДерево элементов: как разбирать субэлементы дочерних узлов

<?xml version="1.0" encoding="UTF-8"?> 
<GetOrdersResponse xmlns="urn:ebay:apis:eBLBaseComponents"> 
<Ack>Success</Ack> 
<Version>857</Version> 
<Build>E857_INTL_APIXO_16643800_R1</Build> 
<PaginationResult> 
    <TotalNumberOfPages>1</TotalNumberOfPages> 
    <TotalNumberOfEntries>2</TotalNumberOfEntries> 
</PaginationResult> 
<HasMoreOrders>false</HasMoreOrders> 
<OrderArray> 
    <Order> 
     <OrderID>221362908003-1324471823012</OrderID> 
     <CheckoutStatus> 
      <eBayPaymentStatus>NoPaymentFailure</eBayPaymentStatus> 
      <LastModifiedTime>2014-02-03T12:08:51.000Z</LastModifiedTime> 
      <PaymentMethod>PaisaPayEscrow</PaymentMethod> 
      <Status>Complete</Status> 
      <IntegratedMerchantCreditCardEnabled>false</IntegratedMerchantCreditCardEnabled> 
     </CheckoutStatus> 
    </Order> 
    <Order> ... 
    </Order> 
    <Order> ... 
    </Order> 
</OrderArray> 
</GetOrdersResponse> 

Я хочу, чтобы разобрать 6-й дочерний XML() Я могу получить значение подэлементов по индексу. Например, если я хочу OrderID первого порядка, я могу использовать root[5][0][0].text. Но я хотел бы получить значения subElements по имени. Я пробовал использовать следующий код, но ничего не печатает:

tree = ET.parse('response.xml') 
root = tree.getroot() 
for child in root: 
    try: 
     for ids in child.find('Order').find('OrderID'): 
      print ids.text 
    except: 
     continue 

Не мог бы кто-нибудь помочь мне. Спасибо

+0

Удалите «try-except-continue» и опубликуйте трассировку, которую вы получите. –

+0

@NigelTufnel: Traceback (самый последний звонок последний):. Файл "test.py", строка 7, в для ид в child.find ('Order') найти ('OrderID'): AttributeError: «NoneType 'объект не имеет атрибута' find ' – nish

ответ

2

Поскольку XML-документ имеет декларацию пространства имен (xmlns="urn:ebay:apis:eBLBaseComponents"), вы должны использовать универсальные имена при обращении к элементам документа. Например, вам нужно {urn:ebay:apis:eBLBaseComponents}OrderID вместо OrderID.

Этот фрагмент кода печатает все OrderIDs в документе:

from xml.etree import ElementTree as ET 

NS = "urn:ebay:apis:eBLBaseComponents" 

tree = ET.parse('response.xml') 

for elem in tree.iter("*"): # Use tree.getiterator("*") in Python 2.5 and 2.6 
    if elem.tag == '{%s}OrderID' % NS: 
     print elem.text 

См http://effbot.org/zone/element-namespaces.htm подробности о ElementTree и пространств имен.

1

Старайтесь избегать цепочки ваших находок. Если ваш первый find ничего не нашел, он вернет None.

for child in root: 
    order = child.find('Order') 
    if order is not None: 
     ids = order.find('OrderID') 
     print ids.text 
+0

То же самое снова. Не печатает ничего – nish

+0

Вы уверены? Я просто проверил ваш ввод и распечатывал текст OrderID. – Rod

+0

Да. Хотя ваш код правильный. Я ничего не смог напечатать, потому что мой корневой тег был ''. При удалении xmlns я смог распечатать идентификаторы – nish

1

Вы можете найти OrderArray первого, а затем просто перебирать свои ребенок по имени:

tree = ET.parse('response.xml') 
root = tree.getroot() 
order_array = root.find("OrderArray") 
for order in order_array.findall('Order'): 
    order_id_element = order.find('OrderID') 
    if order_id_element is not None: 
     print order_id_element.text 

примечания стороны. Никогда не используйте except: continue. Он скрывает любое исключение, которое вы получаете, и делает отладки очень тяжело.

+0

Nigel, я получаю эту ошибку: 'для заказа в order_array.findall ('Order'): AttributeError: объект« NoneType »не имеет атрибута« findall » – nish

+0

Ответ Найджел работает для меня с данным вводом. Соответствует ли ваш ввод тем, что вы показываете в своем вопросе? Немного лучше, чем у меня, так как он ограничивает детей «OrderArray». – Rod

+0

Выяснилось, что он не работает из-за xmlns. Выяснение того, как я могу программно игнорировать xmlns. – nish

Смежные вопросы