根据条件从 XML 个文件中删除重复条目。
Remove Duplicate entries from XML files, based on the condition.
我有一个长 XML 文件列表,其中包含数据列表。基于"ID",我想从文件中删除一些节点。如果 ID 值重复且没有元数据,那么我想保留具有元数据的文件节点并删除其他文件节点。
如果两次看到相同的 ID 值并且都没有元数据,则保留第一个并删除第二个。
Input.xml
<?xml version="1.0"?>
<Def check="">
-<ID Elm="Front Sonar" ID="Opt-0001"/>
-<ID Elm="Rear Sonar" ID="Opt-0002">
<BlockID Wid="100" Auto="true"/>
<Check Auto="true" Siz="20" Nam="Fonts"/>
<Update Auto="true" Nam="Styles"/>
-<Updates Auto="true">
<Update Name="Type_1"/>
<Update Name="Type_21"/>
</Updates>
</ID>
-<ID Elm="Sonar Settings" ID="Opt-0003">
<BlockID Wid="80" Auto="true"/>
<Check Auto="true" Siz="2" Nam="Fun"/>
<Update Auto="true" Nam="done"/>
-<Updates Auto="true">
<Update Name="Type_31"/>
<Update Name="Type_2"/>
</Updates>
</ID>
-<ID Elm="Sonar" ID="Opt-0004">
<!-- no Elm reference found -->
</ID>
-<ID Elm="Menu" ID="ValOpt-0001">
<!-- no Elm reference found -->
</ID>
-<ID Elm="Cancel" ID="ValOpt-0002"/>
-<ID Elm="Go Home" ID="ValOpt-0003"/>
-<ID Elm="Group" ID="Opt-0001">
<!-- no Elm reference found -->
</ID>
-<ID Elm="School" ID="Opt-0002">
<!-- no Elm reference found -->
</ID>
-<ID Elm="Book" ID="Opt-0003">
<!-- no Elm reference found -->
</ID>
-<ID Elm="Lang" ID="ValOpt-0001">
<BlockID Wid="100" Auto="true"/>
<Check Auto="true" Siz="20" Nam="Fonts"/>
<Update Auto="true" Nam="Styles"/>
-<Updates Auto="true">
<Update Name="Type_1"/>
<Update Name="Type_21"/>
</Updates>
</ID>
-<ID Elm="Back" ID="ValOpt-0002">
<BlockID Wid="80" Auto="true"/>
<Check Auto="true" Siz="2" Nam="Fun"/>
<Update Auto="true" Nam="done"/>
-<Updates Auto="true">
<Update Name="Type_31"/>
<Update Name="Type_2"/>
</Updates>
</ID>
-<ID Elm="Exit" ID="ValOpt-0003"/>
</Def>
预计Output.xml
<?xml version="1.0"?>
<Def check="">
-<ID Elm="Front Sonar" ID="Opt-0001"/>
-<ID Elm="Rear Sonar" ID="Opt-0002">
<BlockID Wid="100" Auto="true"/>
<Check Auto="true" Siz="20" Nam="Fonts"/>
<Update Auto="true" Nam="Styles"/>
-<Updates Auto="true">
<Update Name="Type_1"/>
<Update Name="Type_21"/>
</Updates>
</ID>
-<ID Elm="Sonar Settings" ID="Opt-0003">
<BlockID Wid="80" Auto="true"/>
<Check Auto="true" Siz="2" Nam="Fun"/>
<Update Auto="true" Nam="done"/>
-<Updates Auto="true">
<Update Name="Type_31"/>
<Update Name="Type_2"/>
</Updates>
</ID>
-<ID Elm="Sonar" ID="Opt-0004">
<!-- no Elm reference found -->
</ID>
-<ID Elm="Cancel" ID="ValOpt-0002"/>
-<ID Elm="Go Home" ID="ValOpt-0003"/>
-<ID Elm="Group" ID="Opt-0001">
<!-- no Elm reference found -->
</ID>
-<ID Elm="Lang" ID="ValOpt-0001">
<BlockID Wid="100" Auto="true"/>
<Check Auto="true" Siz="20" Nam="Fonts"/>
<Update Auto="true" Nam="Styles"/>
-<Updates Auto="true">
<Update Name="Type_1"/>
<Update Name="Type_21"/>
</Updates>
</ID>
-<ID Elm="Back" ID="ValOpt-0002">
<BlockID Wid="80" Auto="true"/>
<Check Auto="true" Siz="2" Nam="Fun"/>
<Update Auto="true" Nam="done"/>
-<Updates Auto="true">
<Update Name="Type_31"/>
<Update Name="Type_2"/>
</Updates>
</ID>
</Def>
使用元素树,我尝试检查
如果行以“”开头
#从列表中删除元素。
别的
打印 "Element has meta data"
但不幸的是我的函数没有进入循环本身......我总是在其他条件下得到打印语句。对此有任何帮助吗????
预期的输出仍然有一些重复。以下代码的输出与预期不同,但它实际上删除了所有重复项:
from lxml import etree
xml_input = 'Input.xml'
xml_output = 'Output.xml'
with open(xml_input) as xml:
root = etree.XML(xml.read())
#create dictionary where key is an ID and value is a list of nodes with the ID
node_dict = {}
for node in root.xpath('//*[@ID]'):
try:
node_dict[node.get('ID')].append(node)
except KeyError:
node_dict[node.get('ID')] = [node]
for key, nodes in node_dict.iteritems():
#find all nodes with childs
nodes_with_childs = [node for node in nodes if len(node.xpath('./*')) > 0]
#leave only first node with childs, remove other nodes
if len(nodes_with_childs) > 0:
for node in set(nodes) - set([nodes_with_childs[0]]):
node.getparent().remove(node)
else:
#leave only first node, remove other nodes
for node in nodes[1:]:
node.getparent().remove(node)
with open(xml_output, 'w') as xml:
xml.write(etree.tostring(root, xml_declaration=True))
我有一个长 XML 文件列表,其中包含数据列表。基于"ID",我想从文件中删除一些节点。如果 ID 值重复且没有元数据,那么我想保留具有元数据的文件节点并删除其他文件节点。 如果两次看到相同的 ID 值并且都没有元数据,则保留第一个并删除第二个。
Input.xml
<?xml version="1.0"?>
<Def check="">
-<ID Elm="Front Sonar" ID="Opt-0001"/>
-<ID Elm="Rear Sonar" ID="Opt-0002">
<BlockID Wid="100" Auto="true"/>
<Check Auto="true" Siz="20" Nam="Fonts"/>
<Update Auto="true" Nam="Styles"/>
-<Updates Auto="true">
<Update Name="Type_1"/>
<Update Name="Type_21"/>
</Updates>
</ID>
-<ID Elm="Sonar Settings" ID="Opt-0003">
<BlockID Wid="80" Auto="true"/>
<Check Auto="true" Siz="2" Nam="Fun"/>
<Update Auto="true" Nam="done"/>
-<Updates Auto="true">
<Update Name="Type_31"/>
<Update Name="Type_2"/>
</Updates>
</ID>
-<ID Elm="Sonar" ID="Opt-0004">
<!-- no Elm reference found -->
</ID>
-<ID Elm="Menu" ID="ValOpt-0001">
<!-- no Elm reference found -->
</ID>
-<ID Elm="Cancel" ID="ValOpt-0002"/>
-<ID Elm="Go Home" ID="ValOpt-0003"/>
-<ID Elm="Group" ID="Opt-0001">
<!-- no Elm reference found -->
</ID>
-<ID Elm="School" ID="Opt-0002">
<!-- no Elm reference found -->
</ID>
-<ID Elm="Book" ID="Opt-0003">
<!-- no Elm reference found -->
</ID>
-<ID Elm="Lang" ID="ValOpt-0001">
<BlockID Wid="100" Auto="true"/>
<Check Auto="true" Siz="20" Nam="Fonts"/>
<Update Auto="true" Nam="Styles"/>
-<Updates Auto="true">
<Update Name="Type_1"/>
<Update Name="Type_21"/>
</Updates>
</ID>
-<ID Elm="Back" ID="ValOpt-0002">
<BlockID Wid="80" Auto="true"/>
<Check Auto="true" Siz="2" Nam="Fun"/>
<Update Auto="true" Nam="done"/>
-<Updates Auto="true">
<Update Name="Type_31"/>
<Update Name="Type_2"/>
</Updates>
</ID>
-<ID Elm="Exit" ID="ValOpt-0003"/>
</Def>
预计Output.xml
<?xml version="1.0"?>
<Def check="">
-<ID Elm="Front Sonar" ID="Opt-0001"/>
-<ID Elm="Rear Sonar" ID="Opt-0002">
<BlockID Wid="100" Auto="true"/>
<Check Auto="true" Siz="20" Nam="Fonts"/>
<Update Auto="true" Nam="Styles"/>
-<Updates Auto="true">
<Update Name="Type_1"/>
<Update Name="Type_21"/>
</Updates>
</ID>
-<ID Elm="Sonar Settings" ID="Opt-0003">
<BlockID Wid="80" Auto="true"/>
<Check Auto="true" Siz="2" Nam="Fun"/>
<Update Auto="true" Nam="done"/>
-<Updates Auto="true">
<Update Name="Type_31"/>
<Update Name="Type_2"/>
</Updates>
</ID>
-<ID Elm="Sonar" ID="Opt-0004">
<!-- no Elm reference found -->
</ID>
-<ID Elm="Cancel" ID="ValOpt-0002"/>
-<ID Elm="Go Home" ID="ValOpt-0003"/>
-<ID Elm="Group" ID="Opt-0001">
<!-- no Elm reference found -->
</ID>
-<ID Elm="Lang" ID="ValOpt-0001">
<BlockID Wid="100" Auto="true"/>
<Check Auto="true" Siz="20" Nam="Fonts"/>
<Update Auto="true" Nam="Styles"/>
-<Updates Auto="true">
<Update Name="Type_1"/>
<Update Name="Type_21"/>
</Updates>
</ID>
-<ID Elm="Back" ID="ValOpt-0002">
<BlockID Wid="80" Auto="true"/>
<Check Auto="true" Siz="2" Nam="Fun"/>
<Update Auto="true" Nam="done"/>
-<Updates Auto="true">
<Update Name="Type_31"/>
<Update Name="Type_2"/>
</Updates>
</ID>
</Def>
使用元素树,我尝试检查
如果行以“”开头
#从列表中删除元素。
别的
打印 "Element has meta data"
但不幸的是我的函数没有进入循环本身......我总是在其他条件下得到打印语句。对此有任何帮助吗????
预期的输出仍然有一些重复。以下代码的输出与预期不同,但它实际上删除了所有重复项:
from lxml import etree
xml_input = 'Input.xml'
xml_output = 'Output.xml'
with open(xml_input) as xml:
root = etree.XML(xml.read())
#create dictionary where key is an ID and value is a list of nodes with the ID
node_dict = {}
for node in root.xpath('//*[@ID]'):
try:
node_dict[node.get('ID')].append(node)
except KeyError:
node_dict[node.get('ID')] = [node]
for key, nodes in node_dict.iteritems():
#find all nodes with childs
nodes_with_childs = [node for node in nodes if len(node.xpath('./*')) > 0]
#leave only first node with childs, remove other nodes
if len(nodes_with_childs) > 0:
for node in set(nodes) - set([nodes_with_childs[0]]):
node.getparent().remove(node)
else:
#leave only first node, remove other nodes
for node in nodes[1:]:
node.getparent().remove(node)
with open(xml_output, 'w') as xml:
xml.write(etree.tostring(root, xml_declaration=True))