Установить значение файла XML рекурсивно с помощью Python ElementTree? - PullRequest
0 голосов
/ 25 января 2011

Мне дан XML-файл следующим образом.

<?xml version="1.0" encoding="UTF-8"?>
<A value="?">
    <B value="?">
        <C value="10"/>
        <C value ="20"/>
    </B>
    <B value="?">
        <C value = "5" />
        <C value = "10" />
    </B>
</A>

Как можно суммировать значение дочернего узла для рекурсивной установки родителя?

<?xml version="1.0" encoding="UTF-8"?>
<A value="45">
    <B value="30">
        <C value="10"/>
        <C value ="20"/>
    </B>
    <B value="15">
        <C value = "5" />
        <C value = "10" />
    </B>
</A>

Ответы [ 2 ]

2 голосов
/ 25 января 2011

Следующий код был запущен без изменений в Python 3.1.3 (показан) и Python 2.7.1 (не показан).Функция, которая выполняет всю работу, не зависит от версии.Возможно, вы захотите изменить другие биты (синтаксический анализ файла, а не строки, импортирование какой-либо другой реализации ElementTree и т. Д.) В соответствии с вашими потребностями.

   >>> xml_in = """
    ... <A value="?">
    ...     <B value="?">
    ...         <C value="10"/>
    ...         <C value ="20"/>
    ...     </B>
    ...     <B value="?">
    ...         <C value = "5" />
    ...         <C value = "10" />
    ...     </B>
    ... </A>
    ... """
    >>> import xml.etree.ElementTree as et
    >>> def updated_value(elem):
    ...     value = elem.get('value')
    ...     if value != '?': return int(value)
    ...     total = sum(updated_value(child) for child in elem)
    ...     elem.set('value', str(total))
    ...     return total
    ...
    >>> root = et.fromstring(xml_in)
    >>> print("grand total is", updated_value(root))
    grand total is 45
    >>> import sys; nbytes = sys.stdout.write(et.tostring(root) + '\n')
    <A value="45">
        <B value="30">
            <C value="10" />
            <C value="20" />
        </B>
        <B value="15">
            <C value="5" />
            <C value="10" />
        </B>
    </A>
    >>>
1 голос
/ 25 января 2011

Если вам нужно конкретно рекурсивное решение, тогда @ Джон Джин Мачин в порядке.Но вы можете сделать это итеративно:

from xml.etree import cElementTree as etree # adjust it for your python version

for ev, el in etree.iterparse('you_file.xml'):
    if el.get('value') == '?':
       el.set('value', str(sum(int(n.get('value')) for n in el)))

print(etree.tostring(el))

Вывод

<A value="45">
    <B value="30">
        <C value="10" />
        <C value="20" />
    </B>
    <B value="15">
        <C value="5" />
        <C value="10" />
    </B>
</A>
...