用 Python 计算 xml 表达式的值

2019-10-13 20:52:45 +08:00
 rickyleegee
<expression>
<plus>
    <int value="5"/>
    <int value="10"/>
    <times>
        <int value="3"/>
        <minus>
            <int value="4"/>
            <plus>
              <int value="-1000"/>
	          <int value="999"/>                   
            </plus>
        </minus>
    </times>
</plus>
</expression>

这是一个 xml 的文件 读作 5+10+(3*(4-(-1000+999))) 请问要怎么样才能在 python 里面引用这个 xml 文件来计算最终的答案呢?

2292 次点击
所在节点    Python
5 条回复
Nagase
2019-10-13 22:23:53 +08:00
int value 算关键字吧,吧后面的放数组里
necomancer
2019-10-14 01:37:58 +08:00
calc = {'plus' : lambda x, y: x+y, 'minus':lambda x,y:x-y, 'times':lambda x,y: x*y}
data = [5, 10, "plus",3, 4, -1000,999, "plus", "minus", "times","plus"]
def eval_rp(lst):
.... stack = []
....for item in lst:
....if item not in ["plus", "minus", "times"]:
........ stack.append(item)
.... else:
........b, a = stack.pop(), stack.pop()
........res = calc[item](a, b)
........stack.append(res)
....return stack[0]

算符顺序为 xml 关闭节的顺序。注意(+ 1 2 3 4..) 这样的情况就好。
rickyleegee
2019-10-14 14:35:47 +08:00
@necomancer 谢谢你的方法 但如果不使用 data = []的方式 能不能是直接调用 xml 文件来计算的呢?
necomancer
2019-10-14 15:00:14 +08:00
@rickyleegee 我很久没用过 xml 那个解析器了,你可以看看 python 读 xml 的那个库。读进来 xml 然后根据节的关系算就行,或者把节转换成逆波兰表示法。
准确说应该读成:
data = [5, 10, 3, 4, -1000,999, "plus", "minus", "times","plus", "plus"]
算符顺序是 xml 节关闭的顺序,但如果某节内多过两个子节,那么算符需要每两个子节重复一次,所以最后多一个 plus
zzz686970
2019-10-15 18:15:51 +08:00
`````
import xml.etree.ElementTree as ET

test = """
<expression>
<plus>
<int value="5"/>
<int value="10"/>
<times>
<int value="3"/>
<minus>
<int value="4"/>
<plus>
<int value="-1000"/>
<int value="999"/>
</plus>
</minus>
</times>
</plus>
</expression>
"""
data = []
keys = ['minus','plus','times']
xmlTree = ET.fromstring(test)
for ele in xmlTree.iter():
if ele.tag in keys:
data.append(ele.tag)
elif 'value' in ele.attrib:
data.append(int(ele.attrib.get('value')))

# data = ['plus', 5, 10, 'times', 3, 'minus', 4, 'plus', -1000, 999]
calc = {'plus': lambda x, y: x+y, 'minus': lambda x, y: x-y, 'times': lambda x, y: x * y}
def calc_data(lst):
stack = []
for item in lst:
if item not in calc:
stack.append(item)
else:
while len(stack) > 1:
a, b = stack.pop(), stack.pop()

res = calc[item](a, b)
stack.append(res)

return stack[0]
print(calc_data(data[::-1]))
```````

在楼上的基础上测试了一下,感谢 @necomancer

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/608926

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX