2016-04-03 24 views
0

私は長いXMLファイルのリストを持ち、データのリストを持っています。 "ID"に基づいて、ファイルからいくつかのノードを削除したいと思います。 ID値を繰り返してメタデータを持たない場合、メタデータを持つファイルノードを保持し、他のノードを削除したい 同じID値が2回見られ、両方にメタデータがない場合は、1番目を保持して2番目を削除します。要素ツリーを使用して条件に基づいて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> 

のOutput.xml期待

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> 

、私は "ラインstarteswith場合 のために、リストから" #removeのelemetをチェックしてみました。 else "要素はメタデータを持っています"
残念ながら私の関数はループ自体には入っていません....私はいつもelse条件でprintステートメントを取得します。これについての助け?

答えて

0

予想される出力にはまだ重複があります。コードは以下の出力が予想よりも異なっているが、それは実際にすべての重複を削除します。

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)) 
+0

それは完全に正常に動作します...ありがとう... – HARPAL

+0

は、ノード内のテキストの一部に特殊文字が... 1問題を発見しました。 ..対処XMLファイルは、特殊文字のいくつかのジャンク値を見ることができます...どのようにこれを処理することができますか? – HARPAL

+0

私のInput.xmlファイルに次のような行があります "" 重複したエントリを削除して内容をoutput.xmlにコピーした後その値は HARPAL

関連する問題