Python анализирует XML для получения определенных значений [duplicate]

Это одно из мест, с помощью которого привязка данных, используемая во многих новых фреймворках JavaScript, будет очень полезна для вас ...

Итак, если вы используете Angular, React или любые другие фреймворки, которые делают два способа связывания данных, эта проблема просто исправлена ​​для вас, поэтому простым языком ваш результат undefined на первом этапе, поэтому вы получили result = undefined до получения данных, а затем, как только вы получите результат , он будет обновляться и присваиваться новому значению, которое отвечает на ваш вызов Ajax ...

Но как вы можете сделать это в чистом javascript или jQuery, например, как вы задали этот вопрос?

Вы можете использовать обратный вызов, обещание и недавно наблюдаемое, чтобы обрабатывать его для вас, например, в обещаниях мы имеем некоторые функции, такие как success () или then (), которые будут выполняться, когда ваши данные будут готовы для вас, с функцией обратного вызова или подписки на наблюдаемые.

Например, в вашем случае, в котором вы используете jQuery, вы можете сделать что-то вроде этого:

$(document).ready(function(){
    function foo() {
        $.ajax({url: "api/data", success: function(data){
            fooDone(data); //after we have data, we pass it to fooDone
        }});
    };

    function fooDone(data) {
        console.log(data); //fooDone has the data and console.log it
    };

    foo(); //call happens here
});

Для получения дополнительной информации n изучение обещаний и наблюдаемых, которые являются новыми способами для создания асинхронных материалов.

764
задан Martin Thoma 9 April 2015 в 11:47
поделиться

13 ответов

Я предлагаю 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'))

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

585
ответ дан Daniel F 24 August 2018 в 08:17
поделиться
1
ответ дан Ahito 24 August 2018 в 08:17
поделиться

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

6
ответ дан EMP 24 August 2018 в 08:17
поделиться

Я мог бы предложить 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])}
8
ответ дан gatkin 24 August 2018 в 08:17
поделиться

Здесь очень простой, но эффективный код с использованием 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

8
ответ дан Jan Kohila 24 August 2018 в 08:17
поделиться

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

Установка

pip install untangle

Использование

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

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

, доступ к атрибутам с помощью unangle :

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 здесь (вы также увидите, что наиболее распространенные из них были упомянуты в предыдущих ответах ).

8
ответ дан jessag 24 August 2018 в 08:17
поделиться
375
ответ дан Martin Thoma 24 August 2018 в 08:17
поделиться
30
ответ дан myildirim 24 August 2018 в 08:17
поделиться

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}
36
ответ дан sandy 24 August 2018 в 08:17
поделиться
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.

4
ответ дан Souvik Dey 24 August 2018 в 08:17
поделиться

Есть много вариантов. 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   

Как указано @jfs , cElementTree поставляется в комплекте с Python:

  • Python 2: from xml.etree import cElementTree as ElementTree.
  • Python 3: from xml.etree import ElementTree (ускоренная версия C используется автоматически).
76
ответ дан Steven Vascellaro 24 August 2018 в 08:17
поделиться

Python имеет интерфейс для синтаксического анализатора expat.

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
17
ответ дан Tor Valamo 24 August 2018 в 08:17
поделиться

Вы можете использовать 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'
203
ответ дан YOU 24 August 2018 в 08:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: