Pergunta

Estou tendo dificuldade em encontrar um exemplo básico e bom de como analisar XML no python usando a árvore de elementos. Pelo que posso encontrar, essa parece ser a biblioteca mais fácil de usar para analisar XML. Aqui está uma amostra do XML com o qual estou trabalhando:

<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>

Sou capaz de fazer o que preciso, usando um método codificado. Mas preciso que meu código seja um pouco mais dinâmico. Aqui está o que funcionou:

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

Aqui estão algumas coisas que eu tentei, nenhuma delas funcionou, relatando que não conseguiu encontrar o TimeSeries (ou qualquer outra coisa que eu tentei):

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

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

Basicamente, quero carregar o arquivo XML, procurar a tag TimeSeries e iterar através das tags de valor, retornar o tempo DateTime e o valor da própria tag; Tudo o que estou fazendo no exemplo acima, mas não codificando as seções do XML em que estou interessado. Alguém pode me indicar alguns exemplos ou me dar algumas sugestões sobre como trabalhar com isso?


Obrigado por toda a ajuda. Usando as duas sugestões abaixo trabalhadas no arquivo de amostra que eu forneci, no entanto, elas não funcionaram no arquivo completo. Aqui está o erro que recebo do arquivo real quando uso o método de Ed Carrel:

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

Imaginei que havia algo no arquivo real que não gostava, então removi incrementamente as coisas até que funcionasse. Aqui estão as linhas que eu mudei:

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>

Removendo os atributos que possuem 'xsi: ...' corrigiu o problema. O 'xsi: ...' não é válido xml? Será difícil para mim removê -los programaticamente. Algum trabalho sugerido?

Aqui está o arquivo XML completo: http://www.senspace.com/file/lofcpt


Quando eu fiz originalmente essa pergunta, eu não tinha conhecimento de namespaces no XML. Agora que sei o que está acontecendo, não preciso remover os atributos "xsi", que são as declarações de namespace. Eu apenas os incluo nas minhas pesquisas XPath. Ver esta página Para mais informações sobre namespaces no LXML.

Foi útil?

Solução

Então, eu tenho o ElementTree 1.2.6 na minha caixa agora e executei o seguinte código contra o pedaço XML que você postou:

import elementtree.ElementTree as ET

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

print thingy.attrib

e conseguiu o seguinte:

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

Parece ter encontrado o elemento TimeSeries sem precisar usar índices numéricos.

O que seria útil agora é saber o que você quer dizer quando diz "não funciona". Como funciona para mim, com a mesma entrada, é improvável que o ElementTree esteja quebrado de alguma maneira óbvia. Atualize sua pergunta com quaisquer mensagens de erro, retraces ou qualquer coisa que você possa fornecer para nos ajudar a ajudá -lo.

Outras dicas

Se eu entender sua pergunta corretamente:

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

ou se você preferir (e se houver apenas uma ocorrência de timeSeries/values:

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

o findall() o método retorna uma lista de todos os elementos correspondentes, enquanto find() Retorna apenas o primeiro elemento correspondente. O primeiro exemplo atravessa todos os elementos encontrados, o segundo loops sobre os elementos da criança do values elemento, neste caso, levando ao mesmo resultado.

Não vejo onde o problema de não encontrar timeSeries Vem de que, no entanto. Talvez você tenha esquecido o getroot() ligar? (Observe que você realmente não precisa disso, porque também pode trabalhar no próprio elemento, se você mudar a expressão do caminho para por exemplo /timeSeriesResponse/timeSeries/values ou //timeSeries/values)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top