Подтвердить что ты не робот

Анализ XML в Python с использованием примера ElementTree

Мне сложно найти хороший базовый пример того, как разбирать XML в python с помощью Element Tree. Из того, что я могу найти, это самая простая библиотека, используемая для синтаксического анализа XML. Вот пример XML, с которым я работаю:

<timeSeriesResponse>
    <queryInfo>
        <locationParam>01474500</locationParam>
        <variableParam>99988</variableParam>
        <timeParam>
            <beginDateTime>2009-09-24T15:15:55.271</beginDateTime>
            <endDateTime>2009-11-23T15:15:55.271</endDateTime>
        </timeParam>
     </queryInfo>
     <timeSeries name="NWIS Time Series Instantaneous Values">
         <values count="2876">
            <value dateTime="2009-09-24T15:30:00.000-04:00" qualifiers="P">550</value>
            <value dateTime="2009-09-24T16:00:00.000-04:00" qualifiers="P">419</value>
            <value dateTime="2009-09-24T16:30:00.000-04:00" qualifiers="P">370</value>
            .....
         </values>
     </timeSeries>
</timeSeriesResponse>

Я могу делать то, что мне нужно, используя жесткий код. Но мне нужно, чтобы мой код был немного более динамичным. Вот что сработало:

tree = ET.parse(sample.xml)
doc = tree.getroot()

timeseries =  doc[1]
values = timeseries[2]

print child.attrib['dateTime'], child.text
#prints 2009-09-24T15:30:00.000-04:00, 550

Вот несколько вещей, которые я пробовал, ни один из них не работал, сообщая, что они не смогли найти timeSeries (или что-то еще, что я пробовал):

tree = ET.parse(sample.xml)
tree.find('timeSeries')

tree = ET.parse(sample.xml)
doc = tree.getroot()
doc.find('timeSeries')

В принципе, я хочу загрузить файл xml, искать тег timeSeries и перебирать теги значений, возвращая DateTime и значение самого тега; все, что я делаю в приведенном выше примере, но не жесткое кодирование разделов xml, которые меня интересуют. Может ли кто-нибудь указать мне на некоторые примеры или дать мне несколько советов о том, как с этим справиться?


Спасибо за помощь. Тем не менее, использование обоих приведенных ниже рекомендаций работало над предоставленным образцом, но они не работали над полным файлом. Вот ошибка, которую я получаю из реального файла, когда я использую метод Ed Carrel:

 (<type 'exceptions.AttributeError'>, AttributeError("'NoneType' object has no attribute 'attrib'",), <traceback object at 0x011EFB70>)

Я подумал, что в реальном файле ему что-то не нравится, поэтому я постепенно удалял вещи, пока это не сработало. Вот строки, которые я изменил:

originally: <timeSeriesResponse xsi:schemaLocation="a URL I removed" xmlns="a URL I removed" xmlns:xsi="a URL I removed">
 changed to: <timeSeriesResponse>

 originally:  <sourceInfo xsi:type="SiteInfoType">
 changed to: <sourceInfo>

 originally: <geogLocation xsi:type="LatLonPointType" srs="EPSG:4326">
 changed to: <geogLocation>

Удаление атрибутов, имеющих "xsi:...", устраняет проблему. Является ли "xsi:..." недействительным XML? Мне будет сложно удалить их программно. Любая предлагаемая работа вокруг?

Вот полный XML файл: http://www.sendspace.com/file/lofcpt


Когда я изначально задал этот вопрос, я не знал о пространствах имен в XML. Теперь, когда я знаю, что происходит, мне не нужно удалять атрибуты "xsi", которые являются объявлениями пространства имен. Я просто включаю их в свои поисковые запросы. См. эту страницу для получения дополнительной информации об пространствах имен в lxml.

4b9b3361

Ответ 1

Итак, теперь у меня есть ElementTree 1.2.6, и вы запускали следующий код в блоке XML, который вы разместили:

import elementtree.ElementTree as ET

tree = ET.parse("test.xml")
doc = tree.getroot()
thingy = doc.find('timeSeries')

print thingy.attrib

и получил следующий ответ:

{'name': 'NWIS Time Series Instantaneous Values'}

Кажется, он нашел элемент timeSeries без необходимости использования числовых индексов.

Что было бы полезно сейчас, зная, что вы имеете в виду, когда говорите "это не работает". Так как это работает для меня, учитывая тот же ввод, маловероятно, что ElementTree будет разбит каким-то очевидным образом. Обновите свой вопрос с помощью любых сообщений об ошибках, обратных маршрутов или всего, что вы можете предоставить, чтобы помочь нам помочь.

Ответ 2

Если я правильно понял ваш вопрос:

for elem in doc.findall('timeSeries/values/value'):
    print elem.get('dateTime'), elem.text

или если вы предпочитаете (и если есть только одно вхождение timeSeries/values:

values = doc.find('timeSeries/values')
for value in values:
    print value.get('dateTime'), elem.text

Метод findall() возвращает список всех совпадающих элементов, тогда как find() возвращает только первый соответствующий элемент. Первый пример пересекает все найденные элементы, второй - над дочерними элементами элемента values, в этом случае приводя к тому же результату.

Я не вижу, откуда возникает проблема с поиском timeSeries. Может быть, вы просто забыли вызов getroot()? (обратите внимание, что вам это действительно не нужно, потому что вы можете работать и с самим элементом elementtree, если вы измените выражение пути, например, на /timeSeriesResponse/timeSeries/values или //timeSeries/values)