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

StackOverflow https://stackoverflow.com/questions/1786476

  •  21-09-2019
  •  | 
  •  

Вопрос

Мне трудно найти хороший базовый пример того, как анализировать XML в Python с использованием дерева элементов.Насколько мне удалось найти, это самая простая библиотека для анализа 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 и перебрать теги значений, возвращая дату и время и значение самого тега;все, что я делаю в приведенном выше примере, но не жестко кодирую интересующие меня разделы XML.Может ли кто-нибудь указать мне на несколько примеров или дать мне несколько советов о том, как с этим справиться?


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

 (<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», которые являются объявлениями пространства имен.Я просто включаю их в поиск по xpath.Видеть эта страница для получения дополнительной информации о пространствах имен в lxml.

Это было полезно?

Решение

Итак, теперь у меня на компьютере установлена ​​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 разбит каким -то очевидным способом.Обновите свой вопрос, указав любые сообщения об ошибках, обратные трассировки или что-либо еще, что вы можете предоставить, чтобы помочь нам помочь вам.

Другие советы

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

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() вызов?(обратите внимание, что на самом деле вам это не нужно, потому что вы также можете работать с самим элементомtree, если вы измените выражение пути, например, на /timeSeriesResponse/timeSeries/values или //timeSeries/values)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top