我目前正在努力创建一个简单的python脚本,该脚本允许我解析一个XML文件,以获得特定标记的路径.
Input data
我需要解析的XML文件通常如下所示:
<?xml version="1.0" encoding="utf-8"?>
<Document>
<Engineering version="V17"/>
<DocumentInfo>
<ExportSetting>WithDefaults, WithReadOnly</ExportSetting>
</DocumentInfo>
<SW.Blocks.GlobalDB ID="0">
<AttributeList>
<AutoNumber>true</AutoNumber>
<HeaderVersion>0.1</HeaderVersion>
<Interface>
<Sections>
<Section Name="Static">
<Member Name="foo" Datatype="Struct" Remanence="NonRetain" Accessibility="Public">
<Member Name="foo1" Datatype="Bool"></Member>
<Member Name="foo2" Datatype="Struct">
<Member Name="foo2.1" Datatype="Bool"></Member>
<Member Name="foo2.2" Datatype="Int"></Member>
</Member>
</Member>
<Member Name="bar" Datatype="Struct" Remanence="NonRetain" Accessibility="Public">
<Member Name="bar" Datatype="Bool"></Member>
<Member Name="bar 1" Datatype="Bool"></Member>
<Member Name="bar3" Datatype="Bool"></Member>
</Member>
</Section>
</Sections>
</Interface>
</AttributeList>
</SW.Blocks.GlobalDB>
</Document>
Expected output
我只关心这<Member>
个标签,特别是它们的Name
个属性.我想做的是遍历所有这些标记,并获得所有底层子 node (即所有<Member>
个 node 本身没有子 node )的列表,作为一个XML路径列表(仍然只关注Member
个标记).
因此,我希望从给定的示例文件中获得以下结果:
foo.foo1
foo.foo2."foo2.1"
foo.foo2."foo2.2"
bar.bar
bar."bar 1"
bar.bar3
What I tried so far
我编写的第一个脚本基于minidom和一个getElementsByTagName
循环,它 for each Member
在XML体系 struct 中找到它的级别进行计算,并将其与关联的Name
值放在一个列表中.
之后使用第二个循环对该列表进行迭代,并通过级别比较将路径连接起来.
如果它工作了,我会保留那个解决方案(因为他们说,如果它工作了,它并不愚蠢……),但它的行为不正确(根据两个元素之间的级别差异,它计算出正确的路径……或者不).
我以为使用递归循环执行作业(job)会更有效率,但我正在苦苦挣扎.根据StackOverflow上针对类似问题提供的解决方案,我只是写道:
from xml.etree import ElementTree as ET
def find_rec(node, element):
for item in node.findall(element):
yield item
for child in find_rec(item, element):
yield child.attrib['Name']
print(".".join(find_rec(ET.parse("in.xml"), './Member')))
而且它根本不起作用.运行该脚本仅输出一个空格字符,没有任何消息或错误.
用Member
替换./Member
不会改变任何事情,在第二个循环中只写yield child
也不会改变任何事情.
我try 了使用minidom的其他实现,但都没有成功.
有谁能帮我修复这个代码(并解释为什么它不工作……)?
非常感谢!