Использование LXML для извлечения данных, где все элементы не известны заранее
Вопрос
У меня есть несколько файлов SGML, которые примерно стандартизированы. Тем не менее, могут быть данные, содержащиеся в теге, что я не знаю, не знает, прежде чем открыть файл и лично прочитать его. Например, файлы имеют адреса и вообще адреса имеют улицу, город, государство, ZIP и телефон. Каждый элемент адреса указан с тегом
<ADDRESS>
<STREET>One Main Street
<CITY>Gotham City
<ZIP>99999 0123
<PHONE>555-123-5467
</ADDRESS>
Но, например, я обнаружил, что есть теги для страны, Street1, Street2. У меня более 200 тысяч файлов для обработки, и я хочу знать, можно ли вытащить все элементы адресов, не беспокоясь о том, чтобы знать существование неизвестных тегов.
Что я сделал до сих пор
h=fromstring(my_data_in_a_string)
for each in h.cssselect('mail_address'):
each.text_content()
Но то, что я получаю проблематично, потому что я не могу определить, где один элемент заканчивается, а следующий начинается
One Main StreetGotham City99999 0123555-123-5467
Решение
Чтобы получить все теги, мы ейте через документ, как это:
Предположим, что ваша структура XML подобна этому:
<ADDRESS>
<STREET>One Main Street</STREET>
<CITY>Gotham City</CITY>
<ZIP>99999 0123</ZIP>
<PHONE>555-123-5467</PHONE>
</ADDRESS>
Мы разбираем это:
>>> 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
Теперь предположим, что ваш XML имеет дополнительные теги; Теги, о которых вы не знаете. Поскольку мы итерация через XML, вышеуказанный код также вернет эти теги.
<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>
Приведенный выше код возвращается:
ADDRESS
STREET
STREET1
CITY
ZIP
PHONE
COUNTRY
Теперь, если мы хотим получить текст тегов, процедура одинакова. Просто распечатайте тег. Text Text:
>>> for tags in root.iter():
... print tags.text
...
One Main Street
One Second Street
Gotham City
99999 0123
555-123-5467
USA