[Python] Parser XML нужна помощь.

Тема в разделе "Perl, Python, Ruby", создана пользователем Intheomsk, 18 мар 2014.

  1. Intheomsk

    Intheomsk Создатель

    Регистр.:
    1 июл 2013
    Сообщения:
    23
    Симпатии:
    3
    Здравствуйте. Написал парсер для XML файла, но проблема в том, что если в одном из тегов пропущен атрибут - он вылетает. Как сделать проверку на наличие атрибута в тэге (если нет - записать значение none, например) ?
     
  2. errogaht

    errogaht Постоялец

    Регистр.:
    15 май 2013
    Сообщения:
    50
    Симпатии:
    10
    какой библиотекой пользуетесь для парсинга?
    вообще если совершаемое действие не обязательно 100% выполнится то используется конструкция:
    Код:
    try:
        data = GetTag(text)
    except:
        echo 'Unable to parse tag'
        data = ''
     
  3. Intheomsk

    Intheomsk Создатель

    Регистр.:
    1 июл 2013
    Сообщения:
    23
    Симпатии:
    3

    Пользовался xml.dom minidom.
    Перешел на lxml etree - проблема с несуществующим значением решилась, тут результат none выходит какраз.

    Сейчас проблема в другом: одна из частей xml файла:
    Код:
    <UL_ADDRESS DTSTART="28.02.2013" NAMEISPORG="Руководитель">
    <VIDADR ID="1" NAME="Адрес исполнительного органа">
    </VIDADR>
    <ADDRESS INDEKS="644077" DOM="84" KVART="47">
    <REGION ID="1100055" NAME="Омская обл" KOD_KL="55">
    </REGION>
    <GOROD ID="1102823" NAME="Омск г" KOD_KL="55000001000">
    </GOROD>
    <STREET ID="1560208" NAME="Мира пр-кт" KOD_ST="550000010000739">
    </STREET>
    </ADDRESS>
    </UL_ADDRESS>


    Мне нужно отпарсеные данные записывать в файл, есть цикл

    Код:
    for node in tree.iterfind('.//UL_ADDRESS/ADDRESS'):
        print node.get('INDEKS'), node.get('DOM'), node.get('KVART')


    Он отлично забирает значение нужных аттрибутов в ключе адрес, но как в этом же цикле забрать значения аттрибутов region, gorod, street ?

    tree.xpath('.//UL_ADDRESS/ADDRESS/REGION')[0].get('NAME') - забирает только аттрибут с индексом [0], и не дает подставить в индекс 'node'
     
  4. errogaht

    errogaht Постоялец

    Регистр.:
    15 май 2013
    Сообщения:
    50
    Симпатии:
    10
    Там в lxml etree рядом с get который вы используете есть

    getchildren(self)
    Returns all direct children. The elements are returned in document order.
    Может его попробовать?
    выдаст детей этого тега.
    result = node.getchildren
    и потом по идее перебирать
    result[0] - возможно будет REGION
    result[2] - GOROD
    ?
     
    Intheomsk нравится это.
  5. Intheomsk

    Intheomsk Создатель

    Регистр.:
    1 июл 2013
    Сообщения:
    23
    Симпатии:
    3
    Судя по документации:

    Если использовать list(node), то он находит нужые значения:

    Код:
    [<Element REGION at 0x2561fa8>, <Element GOROD at 0x2561288>, <Element STREET at 0x25612b0>]
    [<Element REGION at 0x25612b0>, <Element GOROD at 0x25610a8>, <Element STREET at 0x2561490>]
    [<Element REGION at 0x2561490>, <Element GOROD at 0x2561fa8>, <Element STREET at 0x2561a30>]
    [<Element REGION at 0x2561490>, <Element GOROD at 0x2561a30>, <Element STREET at 0x25612b0>]
    
    Как получить значение аттрибута?
     
    Последнее редактирование: 20 мар 2014
  6. errogaht

    errogaht Постоялец

    Регистр.:
    15 май 2013
    Сообщения:
    50
    Симпатии:
    10
    Вы получили элементы, доступ к атрибуту элемента вот так:

    Код:
    # -*- coding: utf-8 -*-
    import lxml.etree as etree
    
    string = """
    <UL_ADDRESS DTSTART="28.02.2013" NAMEISPORG="Руководитель">
    <VIDADR ID="1" NAME="Адрес исполнительного органа">
    </VIDADR>
    <ADDRESS INDEKS="644077" DOM="84" KVART="47">
    <REGION ID="1100055" NAME="Омская обл" KOD_KL="55">
    </REGION>
    <GOROD ID="1102823" NAME="Омск г" KOD_KL="55000001000">
    </GOROD>
    <STREET ID="1560208" NAME="Мира пр-кт" KOD_ST="550000010000739">
    </STREET>
    </ADDRESS>
    </UL_ADDRESS>
    """
    tree = etree.fromstring(string)
    lol = tree.find('ADDRESS')
    print lol
    list_of_nodes = list(lol)
    print list_of_nodes
    for node in list_of_nodes:
        for name, value in node.items():
            print name, value
    


    на выходе получилось:

    Код:
    <Element ADDRESS at 0x232a8c8>
    [<Element REGION at 0x232adc8>, <Element GOROD at 0x232a418>, <Element STREET at 0x232a468>]
    ID 1100055
    NAME Омская обл
    KOD_KL 55
    ID 1102823
    NAME Омск г
    KOD_KL 55000001000
    ID 1560208
    NAME Мира пр-кт
    KOD_ST 550000010000739
    
    Process finished with exit code 0


    док http://lxml.de/tutorial.html#elements-carry-attributes-as-a-dict
     
    Intheomsk нравится это.
  7. Intheomsk

    Intheomsk Создатель

    Регистр.:
    1 июл 2013
    Сообщения:
    23
    Симпатии:
    3
    Сделал немного по-другому, работает. Появилась еще проблема с кодировкой.

    Некоторые аттрибуты присутствуют не во всех тэгах. Например есть запрос:

    Код:
    node.get('KORP')
    Если значение есть - то должно быть
    Код:
    node.get('KORP').encode('UTF-8')
    . а если значения нет, т.е. None, то так делать нельзя (Nontype не кодируется), то для None должно быть
    Код:
    str(node.get('KORP')).encode('UTF-8')
    Есть мысли ? :)
     
    Последнее редактирование: 20 мар 2014
  8. errogaht

    errogaht Постоялец

    Регистр.:
    15 май 2013
    Сообщения:
    50
    Симпатии:
    10
    Можно сделать такую проверку:

    Код:
    if node.get('KORP'):
        korp = node.get('OGRN').encode('UTF-8')
    else:
        korp = ''
     
  9. Intheomsk

    Intheomsk Создатель

    Регистр.:
    1 июл 2013
    Сообщения:
    23
    Симпатии:
    3
    Не выходит. AttributeError: 'NoneType' object has no attribute 'encode'

    ADD: Прошу прощения, аттрибуты в предыдущем сообщении одинаковые у всех. Поправил пост, вопрос актуален.
     
    Последнее редактирование: 21 мар 2014
  10. errogaht

    errogaht Постоялец

    Регистр.:
    15 май 2013
    Сообщения:
    50
    Симпатии:
    10
    Можно попробовать так:

    Код:
    try:
        korp = node.get('OGRN').encode('UTF-8')
    except:
        korp = ''
    
    или попробовать сделать проверку на тип функцией type()
    Код:
    print type(node.get('OGRN'))
    
    if type(node.get('OGRN')) == something:
        do something