Return 来自任意嵌套 xml 树总和的结果

Return result from arbitrarily nested xml tree sum

我有以下代码在 xml 树上递归(?),它表示一个简单的等式:

root = etree.XML(request.data['expression'])

def addleafnodes(root):
    numbers = []
    for child in root:
        if root.tag != "root" and root.tag != "expression":
            print(root.tag, child.text)

            if child.tag != "add" and child.tag != "multiply":
                numbers.append(int(child.text))
                print("NUMBERS", numbers)
            elif child.tag == "add":
                numbers.append(np.sum(addleafnodes(child)))
                print("NUMBERS", numbers)
            elif child.tag == "multiply":
                numbers.append(np.prod(addleafnodes(child)))
                print("NUMBERS", numbers)
        print("NUMBERS", numbers)
        addleafnodes(child)
    return numbers

newresults = addleafnodes(root)
print("[NEW RESULTS]", newresults)

xml是:

<root>
    <expression>
        <add>
            <add>
                <number>1</number>
                <number>2</number>
            </add>
            <multiply>
                <number>2</number>
                <number>3</number>
            </multiply>
            <add>
                <number>4</number>
                <number>5</number>
            </add>
            <number>3</number>
            <multiply>
                <number>1</number>
                <add>
                    <number>3</number>
                    <number>4</number>
                </add>
            </multiply>
        </add>
    </expression>
</root>

代码似乎一直运行到最后一个循环,当它重置数字列表并似乎再次启动该过程时,失败了。

如何让 python (lxml) 在检查完每个节点后停止?我可能错过了一些重要的事情!

首先,我认为您可以通过断言标签 而不是 不是 来让自己更轻松成为某种东西(例如,尝试删除 != 并替换为 ==)。

一个问题是 addleafnodes(child) 行,它返回了一些东西,但后来又被扔掉了。由于您可以获得返回的数字列表,它应该是 added/multiplied/etc。您可以使用 numbers.extend(somelist) 将它们添加到 numbers 列表中。解释递归有点困难,所以如果你看一下代码,它可能会更有意义。我有时做的是在函数中添加一个 depth 变量并在每次我 "recurse" 时递增它 - 这样,在打印信息时,可能更容易看到哪个 "level" 数字是从哪里回来。

def addleafnodes(root):
    numbers = []
    for child in root:
        if child.tag == "number":
            numbers.append(int(child.text))
        elif child.tag == "add":
            numbers.append(np.sum(addleafnodes(child)))
        elif child.tag == "multiply":
            numbers.append(np.prod(addleafnodes(child)))
        else:
            numbers.extend(addleafnodes(child))
        print("NUMBERS: ", numbers)
    return numbers

newresults = addleafnodes(root)
print("[NEW RESULTS]", newresults)

# outputs:
NUMBERS:  [1]
NUMBERS:  [1, 2]
NUMBERS:  [3]
NUMBERS:  [2]
NUMBERS:  [2, 3]
NUMBERS:  [3, 6]
NUMBERS:  [4]
NUMBERS:  [4, 5]
NUMBERS:  [3, 6, 9]
NUMBERS:  [3, 6, 9, 3]
NUMBERS:  [1]
NUMBERS:  [3]
NUMBERS:  [3, 4]
NUMBERS:  [1, 7]
NUMBERS:  [3, 6, 9, 3, 7]
NUMBERS:  [28]
NUMBERS:  [28]
[NEW RESULTS] [28]

另一件事:您已选择允许 <add></add> 中的数字列表。你也可以认为它只有 2 个数字,因为它是一个二元运算,然后依赖于嵌套。同样显然适用于其他 unary/binary/ternary/.. 运营商。

<add>
    <number>1</number>
    <add>
        <number>2</number>
        <number>3</number>
    </add>
</add>

这样,也许您可​​以消除 for-loop,但我不确定它是否会产生其他问题。 :-)