Usando LXML para extrair dados onde todos os elementos não são conhecidos com antecedência
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
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