Вложенные теги XML в Python

У меня есть вложенный XML, который выглядит так:

<data>foo <data1>hello</data1> bar</data>

Я использую minidom, но независимо от того, как я пытаюсь получить значения между «данными», я получаю только «foo», но не «bar».

Еще хуже, если XML такой:

<data><data1>hello</data1> bar</data>

Я получаю только «Нет», что правильно в соответствии с приведенной выше логикой. Итак, я наткнулся на это: http://levdev.wordpress.com/2011/07/29/get-xml-element-value-in-python-using-minidom и пришли к выводу, что это связано с ограничениями minidom?

Поэтому я использовал метод в этом блоге, и теперь я получаю

foo <data1>hello</data1> bar

а также

<data1>hello</data1> bar

что приемлемо. Однако, если я попытаюсь создать новый узел (createTextNode), используя приведенный выше вывод в качестве значений узла, XML станет следующим:

<data>foo &lt;data1&gt;hello&lt;/data1&gt; bar</data>

а также

<data>&lt;data1&gt;hello&lt;/data1&gt; bar</data>

Есть ли способ, которым я могу создать его так, чтобы он выглядел как оригинал? Спасибо.


person Ryuinferno    schedule 28.04.2014    source источник
comment
Я не эксперт по синтаксическому анализу XML, но насколько я понимаю, ваш тег данных содержит три дочерних узла: текстовый узел, содержащий foo , узел элемента для тега ‹data1› и еще один текстовый узел, содержащий bar. Вы должны получить оба текстовых узла, чтобы делать то, что вы хотите. Что касается того, есть ли элегантный способ сделать это в библиотеках XML (или, в частности, в минидоме Python), я не знаю.   -  person pandubear    schedule 28.04.2014
comment
Я думаю, я понимаю, что вы имеете в виду, я свяжусь с вами   -  person Ryuinferno    schedule 28.04.2014
comment
@pandubear, вы правы, текстовых узлов действительно два.   -  person Ryuinferno    schedule 28.04.2014


Ответы (3)


Вы можете использовать дерево элементов. Для xml это очень эффективно как для поиска, так и для создания узла.

взгляните на ссылку ниже

дерево элементов -- руководства смешанный xml

некоторые из примеров создания узла

import xml.etree.ElementTree as ET

  data = ET.Element('data')

data1= ET.SubElement(data, 'data1',attr="value")
data1.text="hello"
data.text="bar"
data1.tail="some code"
ET.dump(data)

вывод :<data>bar<data1 attr="value">hello</data1>some code</data>

person sundar nataraj    schedule 28.04.2014
comment
Да, но как насчет значения за ‹/data1›? то есть <data>bar<data1>hello</data1>foo</data> Под этим я подразумеваю foo - person Ryuinferno; 28.04.2014
comment
я думаю, что это неправильный формат xml.. Но можно попробовать поставить пробел между словом ‹data›bar foo‹data1›hello‹/data1›‹/data› - person sundar nataraj; 28.04.2014
comment
Нет, это действительный XML в зависимости от того, какой проект его использует, например, посмотрите здесь: github.com/CyanogenMod/android_packages_apps_Settings/blob/ - person Ryuinferno; 28.04.2014
comment
@Рюинферно . ПРОВЕРЬТЕ ОБНОВЛЕННЫЙ КОД. ИСПОЛЬЗУЙТЕ ХВОСТ. ПОЛУЧИТЕ ОЖИДАЕМЫЙ РЕЗУЛЬТАТ - person sundar nataraj; 28.04.2014
comment
Спасибо за усилия, но я нашел точный ответ на свой вопрос (используя минидом), размещенный ниже... :) - person Ryuinferno; 28.04.2014
comment
это нормально :) не беспокойтесь .. посмотрите на усилия по написанию кода в минидоме и дереве элементов - person sundar nataraj; 28.04.2014

Используйте следующую функцию, чтобы украсить ваш xml, чтобы его было НАМНОГО легче увидеть... прежде всего..

import xml.dom.minidom as minidom

def prettify(elem):
    """Return a pretty-printed XML string for the Element.  Props goes
    to Maxime from stackoverflow for this code."""
    rough_string = et.tostring(elem, 'utf-8')
    reparsed = minidom.parseString(rough_string)
    return reparsed.toprettyxml(indent="\t")

Это значительно упрощает визуальное перемещение по дереву.

Далее я бы предложил изменить ваш xml, который, я думаю, сделает вашу жизнь намного проще.

Вместо :

<data>foo
    <data1>hello</data1>
    bar
</data>

который не является правильным форматом XML, я бы сохранил ваши «foo» и «bar» как атрибуты

это выглядит так:

<data var1='foo' var2='bar'>
    <data1>hello</data1>
</data>

сделать это с помощью xml.etree.ElementTree:

import xml.etree.ElementTree as ET

data = ET.Element('data', {'var1:'foo', 'var2':'bar'})
data1= ET.SubElement(data, 'data1')
data1.text='hello'
print prettify(data)
person Amazingred    schedule 28.04.2014

Итак, после того, как @pandubear указал, XML:

<data>foo <data1>hello</data1> bar</data>

Имеет два текстовых узла, содержащих «foo» и «bar», поэтому можно выполнить итерацию по всем дочерним узлам в данных и получить значения.

person Ryuinferno    schedule 28.04.2014