Вернуть результат из произвольно вложенной суммы дерева xml - PullRequest
1 голос
/ 04 июня 2019

У меня есть следующий код, который рекурсивно (?) По дереву 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) остановиться, когда он просматривал каждый узел?Я, наверное, пропустил что-то важное!

1 Ответ

1 голос
/ 04 июня 2019

Прежде всего, я думаю, что вы можете облегчить себе задачу, утверждая, что тег является чем-то, а не не чем-то (например, попытайтесь удалить! = И заменить на ==).

Одной из проблем была строка addleafnodes(child), которая возвращала что-то, что затем выбрасывалось. Поскольку вы можете получить список возвращенных чисел, который должен быть добавлен / умножен / и т. Д., Вы можете добавить их в список numbers с помощью numbers.extend(somelist). Объяснить рекурсии немного сложно, поэтому, возможно, если вы посмотрите на код, это будет иметь больше смысла. Иногда я добавляю в функцию переменную depth и увеличиваю ее каждый раз, когда я «рекурсирую» - таким образом, при печати информации может быть легче увидеть, с какого «уровня» и откуда возвращается число.

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 числа, так как это двоичная операция, а затем полагаться на вложение. То же самое относится и к другим унарным / двоичным / троичным / .. операторам.

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

Таким образом, возможно, вы сможете устранить цикл for, но я не уверен, что он создает другие проблемы. : -)

...