Usando LXML para extrair dados onde todos os elementos não são conhecidos com antecedência

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

  •  25-09-2019
  •  | 
  •  

Pergunta

Eu tenho alguns arquivos SGML que são padronizados aproximadamente. No entanto, pode haver dados contidos em uma tag que eu não conheço antes de abrir o arquivo e lê -los pessoalmente. Por exemplo, os arquivos têm endereços e, geralmente, os endereços têm uma rua, uma cidade, um estado, um zip e um telefone. Cada elemento do endereço é indicado com uma tag

 <ADDRESS>
 <STREET>One Main Street
 <CITY>Gotham City
 <ZIP>99999 0123
 <PHONE>555-123-5467
 </ADDRESS>

Mas, por exemplo, descobri que existem tags para o país, Street1, Street2. Tenho mais de 200 mil arquivos para processar e quero saber se é possível retirar todos os elementos dos endereços sem ter que se preocupar em conhecer a existência de tags desconhecidas.

O que eu fiz até agora é

h=fromstring(my_data_in_a_string)
for each in h.cssselect('mail_address'):
    each.text_content()

Mas o que eu entendo é problemático porque não consigo identificar onde um elemento termina e o próximo começa

One Main StreetGotham City99999 0123555-123-5467
Foi útil?

Solução

Para obter todas as tags, nós seguimos através do documento como este:

Suponha que sua estrutura XML seja assim:

<ADDRESS>
 <STREET>One Main Street</STREET>
 <CITY>Gotham City</CITY>
 <ZIP>99999 0123</ZIP>
 <PHONE>555-123-5467</PHONE>
 </ADDRESS>

Nós analisamos:

>>> from lxml import etree
>>> f = etree.parse('foo.xml')  # path to XML file
>>> root = f.getroot() # get the root element
>>> for tags in root.iter(): # iter through the root element
...     print tags.tag       # print all the tags
... 
ADDRESS
STREET
CITY
ZIP
PHONE

Agora, suponha que seu XML também tenha tags extras; Tags que você não conhece. Como estamos iterando o XML, o código acima também retornará essas tags.

<ADDRESS>
         <STREET>One Main Street</STREET>
         <STREET1>One Second Street</STREET1>
        <CITY>Gotham City</CITY>
         <ZIP>99999 0123</ZIP>
         <PHONE>555-123-5467</PHONE>         
         <COUNTRY>USA</COUNTRY>    
</ADDRESS>

O código acima retorna:

ADDRESS
STREET
STREET1
CITY
ZIP
PHONE
COUNTRY

Agora, se queremos obter o texto das tags, o procedimento é o mesmo. Basta imprimir tag.text como este:

>>> for tags in root.iter():
...     print tags.text
... 

One Main Street
One Second Street
Gotham City
99999 0123
555-123-5467
USA
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top