使用Python ElementTree递归设置XML文件的值?

时间:2011-01-24 23:54:45

标签: python xml elementtree

我给出了一个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>

如何将children节点的值相加以递归设置父节点?

<?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 个答案:

答案 0 :(得分:2)

以下代码在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 :(得分:1)

如果您需要专门的递归解决方案,那么@John Machin's answer就可以了。但你可以迭代地做到这一点:

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>