Как обрабатывать XML в Python?

У меня много строк в базе данных, содержащей xml, и я пытаюсь написать скрипт Python, который будет проходить через эти строки и подсчитывать количество экземпляров определенного атрибута узла. Например, мое дерево выглядит так:

<foo> <bar> <type foobar="1"/> <type foobar="2"/> </bar> </foo> 

Как я могу получить доступ к атрибутам 1 и 2 в XML с помощью Python?

  • Как извлечь атрибут xml с помощью Python ElementTree
  • Что это такое (cid: 51) в выводе pdf2txt?
  • XML-синтаксический анализ в python: expaterror не является корректным
  • как использовать пустые пространства имен в запросе lxml xpath?
  • Python ElementTree find () не соответствует в файле kml
  • Как сократить длинные выражения XPath со многими альтернативами OR?
  • Что такое хороший синтаксический анализатор потока XML для Python?
  • слияние файлов xml с использованием python ElementTree
  • 15 Solutions collect form web for “Как обрабатывать XML в Python?”

    Я предлагаю ElementTree . Существуют и другие совместимые реализации одного и того же API, такие как lxml и cElementTree в самой стандартной библиотеке Python; но в этом контексте то, что они в основном добавляют, является еще большей скоростью – легкость программирования зависит от API, который определяет ElementTree .

    После создания экземпляра e элемента из XML, например с помощью функции XML , или путем разбора файла с чем-то вроде

     import xml.etree.ElementTree e = xml.etree.ElementTree.parse('thefile.xml').getroot() 

    или любой из многих других способов, показанных в ElementTree , вы просто делаете что-то вроде:

     for atype in e.findall('type'): print(atype.get('foobar')) 

    и аналогичные, обычно довольно простые, шаблоны кода.

    minidom является самым быстрым и довольно прямым:

    XML:

     <data> <items> <item name="item1"></item> <item name="item2"></item> <item name="item3"></item> <item name="item4"></item> </items> </data> 

    ПИТОН:

     from xml.dom import minidom xmldoc = minidom.parse('items.xml') itemlist = xmldoc.getElementsByTagName('item') print(len(itemlist)) print(itemlist[0].attributes['name'].value) for s in itemlist: print(s.attributes['name'].value) материалов from xml.dom import minidom xmldoc = minidom.parse('items.xml') itemlist = xmldoc.getElementsByTagName('item') print(len(itemlist)) print(itemlist[0].attributes['name'].value) for s in itemlist: print(s.attributes['name'].value) материалов from xml.dom import minidom xmldoc = minidom.parse('items.xml') itemlist = xmldoc.getElementsByTagName('item') print(len(itemlist)) print(itemlist[0].attributes['name'].value) for s in itemlist: print(s.attributes['name'].value) 

    ВЫВОД

     4 item1 item1 item2 item3 item4 

    Вы можете использовать BeautifulSoup

     from bs4 import BeautifulSoup x="""<foo> <bar> <type foobar="1"/> <type foobar="2"/> </bar> </foo>""" y=BeautifulSoup(x) >>> y.foo.bar.type["foobar"] u'1' >>> y.foo.bar.findAll("type") [<type foobar="1"></type>, <type foobar="2"></type>] >>> y.foo.bar.findAll("type")[0]["foobar"] u'1' >>> y.foo.bar.findAll("type")[1]["foobar"] u'2' 

    Есть много вариантов. cElementTree отлично смотрится, если проблема и скорость использования памяти. Он имеет очень мало накладных расходов по сравнению с простым чтением в файле с использованием readlines .

    Соответствующие показатели можно найти в таблице ниже, скопированной с веб-сайта cElementTree :

     library time space xml.dom.minidom (Python 2.1) 6.3 s 80000K gnosis.objectify 2.0 s 22000k xml.dom.minidom (Python 2.4) 1.4 s 53000k ElementTree 1.2 1.6 s 14500k ElementTree 1.2.4/1.3 1.1 s 14500k cDomlette (C extension) 0.540 s 20500k PyRXPU (C extension) 0.175 s 10850k libxml2 (C extension) 0.098 s 16000k readlines (read as utf-8) 0.093 s 8850k cElementTree (C extension) --> 0.047 s 4900K <-- readlines (read as ascii) 0.032 s 5050k 

    Как указано в @ jf-sebastian, cElementTree поставляется в комплекте с python: «На Python 2: from xml.etree import cElementTree as ElementTree . На Python 3: from xml.etree import ElementTree (ускоренная версия C используется автоматически)».

    lxml.objectify действительно прост.

    Принимая ваш образец текста:

     from lxml import objectify from collections import defaultdict count = defaultdict(int) root = objectify.fromstring(text) for item in root.bar.type: count[item.attrib.get("foobar")] += 1 print dict(count) 

    Вывод:

     {'1': 1, '2': 1} 

    Я предлагаю xmltodict для простоты.

    Он анализирует ваш xml на OrderedDict;

     >>> e = '<foo> <bar> <type foobar="1"/> <type foobar="2"/> </bar> </foo> ' >>> import xmltodict >>> result = xmltodict.parse(e) >>> result OrderedDict([(u'foo', OrderedDict([(u'bar', OrderedDict([(u'type', [OrderedDict([(u'@foobar', u'1')]), OrderedDict([(u'@foobar', u'2')])])]))]))]) >>> result['foo'] OrderedDict([(u'bar', OrderedDict([(u'type', [OrderedDict([(u'@foobar', u'1')]), OrderedDict([(u'@foobar', u'2')])])]))]) >>> result['foo']['bar'] OrderedDict([(u'type', [OrderedDict([(u'@foobar', u'1')]), OrderedDict([(u'@foobar', u'2')])])]) 

    Python имеет интерфейс с парсером expat xml.

     xml.parsers.expat 

    Это не проверяющий парсер, поэтому плохой xml не будет пойман. Но если вы знаете, что ваш файл верен, то это очень хорошо, и вы, вероятно, получите точную информацию, которую хотите, и можете отбросить остальное на лету.

     stringofxml = """<foo> <bar> <type arg="value" /> <type arg="value" /> <type arg="value" /> </bar> <bar> <type arg="value" /> </bar> </foo>""" count = 0 def start(name, attr): global count if name == 'type': count += 1 p = expat.ParserCreate() p.StartElementHandler = start p.Parse(stringofxml) print count # prints 4 

    Я все еще новичок Python самостоятельно, но у меня сложилось впечатление, что ElementTree – это современное состояние в разборе и обработке XML на Python.

    У Марка Пилигрима есть хороший раздел по анализу XML с ElementTree в его книге Dive Into Python 3 .

    Здесь очень простой, но эффективный код с использованием cElementTree .

     try: import cElementTree as ET except ImportError: try: # Python 2.5 need to import a different module import xml.etree.cElementTree as ET except ImportError: exit_err("Failed to import cElementTree from any known place") def find_in_tree(tree, node): found = tree.find(node) if found == None: print "No %s in file" % node found = [] return found # Parse a xml file (specify the path) def_file = "xml_file_name.xml" try: dom = ET.parse(open(def_file, "r")) root = dom.getroot() except: exit_err("Unable to open and parse input definition file: " + def_file) # Parse to find the child nodes list of node 'myNode' fwdefs = find_in_tree(root,"myNode") 

    Источник:

    http://www.snip2code.com/Snippet/991/python-xml-parse?fromPage=1

    Я нахожу Python xml.dom и xml.dom.minidom довольно просто. Имейте в виду, что DOM не подходит для больших объемов XML, но если ваш вход довольно мал, это будет работать нормально.

    Чтобы добавить еще одну возможность, вы можете использовать unangle , так как это простая библиотека xml-to-python-object. Здесь у вас есть пример:

    Монтаж

     pip install untangle 

    Применение

    Ваш xml-файл (немного изменился):

     <foo> <bar name="bar_name"> <type foobar="1"/> </bar> </foo> 

    доступ к атрибутам с неполадкой :

     import untangle obj = untangle.parse('/path_to_xml_file/file.xml') print obj.foo.bar['name'] print obj.foo.bar.type['foobar'] 

    выход будет:

     bar_name 1 

    Более подробную информацию о распутывании можно найти здесь .
    Также (если вам интересно), вы можете найти список инструментов для работы с XML и Python здесь (вы также увидите, что наиболее распространенные из них были упомянуты в предыдущих ответах).

     import xml.etree.ElementTree as ET data = '''<foo> <bar> <type foobar="1"/> <type foobar="2"/> </bar> </foo>''' tree = ET.fromstring(data) lst = tree.findall('bar/type') for item in lst: print item.get('foobar') 

    Это напечатает значение атрибута foobar.

    Ты серьезно ?

    Как насчет проблем безопасности? Используйте defusedxml .

    Это также рекомендуется двумя совами Django .

    Сравнение с defusedxml и другими библиотеками

    Lxml защищен от миллиардов атак смеха и не выполняет поиск по сети по умолчанию.

    libxml2 и lxml не являются непосредственно уязвимыми для gzip-декомпрессионных бомб, но они также не защищают вас от них.

    xml.etree не расширяет сущности и не вызывает ParserError при возникновении объекта.

    minidom не расширяет сущности и просто возвращает нерасширенный объект дословно.

    genshi.input of genshi 0.6 не поддерживает сущность расширения и вызывает ParserError, когда происходит сущность.

    Библиотека имеет (ограниченную) поддержку XInclude, но для ее включения требуется дополнительный шаг.

    Я мог бы предложить declxml .

    Полное раскрытие: я написал эту библиотеку, потому что я искал способ конвертировать между структурами данных XML и Python без необходимости писать десятки строк императивного кода синтаксического анализа / сериализации с помощью ElementTree.

    С помощью declxml вы используете процессоры для декларативного определения структуры вашего XML-документа и способа сопоставления между структурами данных XML и Python. Процессоры используются как для сериализации, так и для синтаксического анализа, а также для базового уровня проверки.

    Анализ в структурах данных Python прост:

     import declxml as xml xml_string = """ <foo> <bar> <type foobar="1"/> <type foobar="2"/> </bar> </foo> """ processor = xml.dictionary('foo', [ xml.dictionary('bar', [ xml.array(xml.integer('type', attribute='foobar')) ]) ]) xml.parse_from_string(processor, xml_string) 

    Что дает результат:

     {'bar': {'foobar': [1, 2]}} 

    Вы также можете использовать один и тот же процессор для сериализации данных в XML

     data = {'bar': { 'foobar': [7, 3, 21, 16, 11] }} xml.serialize_to_string(processor, data, indent=' ') 

    Которая производит следующий выход

     <?xml version="1.0" ?> <foo> <bar> <type foobar="7"/> <type foobar="3"/> <type foobar="21"/> <type foobar="16"/> <type foobar="11"/> </bar> </foo> 

    Если вы хотите работать с объектами вместо словарей, вы можете определить процессоры для преобразования данных в объекты и из них.

     import declxml as xml class Bar: def __init__(self): self.foobars = [] def __repr__(self): return 'Bar(foobars={})'.format(self.foobars) xml_string = """ <foo> <bar> <type foobar="1"/> <type foobar="2"/> </bar> </foo> """ processor = xml.dictionary('foo', [ xml.user_object('bar', Bar, [ xml.array(xml.integer('type', attribute='foobar'), alias='foobars') ]) ]) xml.parse_from_string(processor, xml_string) 

    Которая производит следующий выход

     {'bar': Bar(foobars=[1, 2])} 

    rec.xml: –

     <?xml version="1.0"?> <nodes> <node name="Car" child="Engine"></node> <node name="Engine" child="Piston"></node> <node name="Engine" child="Carb"></node> <node name="Car" child="Wheel"></node> <node name="Wheel" child="Hubcaps"></node> <node name="Truck" child="Engine"></node> <node name="Truck" child="Loading Bin"></node> <node name="Piston" child="Loa"></node> <node name="Spare Wheel" child=""></node> </nodes> 

    par.py:-

     import xml.etree.ElementTree as ET tree = ET.parse('rec.xml') root = tree.getroot() for nodes in root.findall('node'): parent = nodes.attrib.get('name') child = nodes.attrib.get('child') print parent,child 
    Python - лучший язык программирования в мире.