我有一个包含菜单结构的xml文件。我要搜索菜单名称或应用程序名称,如果匹配,则要在树中打印完整路径。
这是xml文件的一部分:
<menu name="main_menu" display="Main Menu">
<menu name="A" display="A"
<menu name="X" display="X" >
<application name="M" display="M"/>
<application name="N" display="N"/>
</menu>
<menu name="B" display="B"
<menu name="Y" display="Y" >
<application name="O" display="O"/>
<application name="P" display="P"/>
</menu>
我正在尝试按XML文件中匹配的名称搜索并打印位置。例如:
如果我搜索"P"
,它将打印"B", "Y", "P"
。
或者如果我搜索"Y"
,它将打印"B", "Y"
。
到目前为止,我已经尝试过:
def findLocation(name):
xmlLocation = "menu.xml"
tree = ET.parse(xmlLocation)
root = tree.getroot()
parent_map = {c:p for p in tree.iter() for c in p}
for item in tree.iterfind('.//menu/..'):
if item.find('menu').text.encode('utf-8') == name:
print parent_map[item].find('name').text
findLocation("Y")
但是它什么也没打印。您能建议我该怎么做吗?
答案 0 :(得分:1)
您可以使用类似这样的功能(递归,但对于深度受限制的xml来说是可以的):
def find_location(tree, target):
stack = []
root = tree.getroot()
def helper(child): # recursive part
name = dict(child.items())['name']
if name == 'target':
return [name]
children = child.getchildren()
for c in children:
ret = helper(c)
if ret and ret[-1] == target:
return [name] + ret
return [name]
# you can cahnge it if you need it, for instance, if only "Main Menu" parsing required
for child in root:
result = helper(child)
if result and result[-1] == target:
return result
return []
用法:
tree = ET.parse("menu.xml")
location = find_location(tree, 'M')
print(location)
Out:
['main_menu', 'A', 'X', 'M']
location = find_location(tree, 'N')
print(location)
Out:
['main_menu', 'A', 'X', 'N']
location = find_location(tree, 'Y')
print(location)
Out:
['main_menu', 'B', 'Y']
location = find_location(tree, 'P')
print(location)
Out:
['main_menu', 'B', 'Y', 'P']
location = find_location(tree, 'Z') # no such name in XML
print(location)
Out:
[]
注意:如果目标名称中有多个元素,则此代码将返回第一次出现的情况。
您可以轻松采用此方法,也可以仅裁剪列表中的第一个元素,然后打印输出:
for node in location[1:]:
print(node)
Out:
'B'
'Y'
'P'
我已经使用了这样的xml(经过精心修改,因为该内容来自发布后的问题):
<?xml version="1.0"?>
<data>
<menu name="main_menu" display="Main Menu">
<menu name="A" display="A" >
<menu name="X" display="X" >
<application name="M" display="M"/>
<application name="N" display="N"/>
</menu>
</menu>
<menu name="B" display="B" >
<menu name="Y" display="Y" >
<application name="O" display="O"/>
<application name="P" display="P"/>
</menu>
</menu>
</menu>
</data>