2016-06-24 14 views
1

私はこのことのために新規です。私のオリジナルのxmlは約8GBなので、オリジナルのxmlに関心のある子供のためのすべての親、祖父母、祖父母などを手動で調べるのは難しいです。興味のある子どもが見つかるまで、すべてのノードを調べようとしています。ですから、country_data.xmlの興味のある子孫までxmlの "スケルトン"構造を作成したいと思います。https://docs.python.org/2/library/xml.etree.elementtree.htmlから。コードのため申し訳ありません:Pythonを使用して特定のXMLノードまでのXML構造を生成する方法は?

def LookThrougStructure(parent, xpath_str, stop_flag): 
    out_str.write('Parent tag: %s\n' % (parent.tag)) 
    for child in parent: 
     if child.tag == my_tag: 
      out_str.write('Child tag: %s\n' % (child.tag)) 
      #my_node_is_found_flag = 1 
      break 
     LookThrougStructure(child, child.tag, 0) 
    return 
import xml.etree.ElementTree as ET 
tree = ET.parse('country_data.xml') 
root = tree.getroot() 
my_tag = 'neighbor' 
out_str = open('xml_structure.txt', 'w') 
LookThrougStructure(root, root.tag, my_tag) 
out_str.close() 

それは間違って動作し、すべてのノードのタグをyelds:

親タグ:データ親タグ:国親タグ:ランク親タグ:年 親タグ:gdppc子タグ:隣人の親タグ:国親タグ: ランク親タグ:年の親タグ:gdppc子タグ:隣人の親 タグ:国親タグ:ランク親タグ:年親タグ:gdppc子供 タグ:隣人

しかし、私はそのような何かをしたいが、(私の興味を持って子供が "隣人" である):

  • データ
      • 隣人

かそれは:/ dat a/country /隣人。 どうしたのですか?

+0

実際の出力を正しい形式で追加することはできますか?私はあなたが望むものをよく理解していません。 –

+0

はい:上記を参照してください。私はrank、year、gdppcのようなものは必要ありません。隣のタグのすべての親ノードだけを見たいと思っています。 –

+0

だから、基本的に祖先は隣人までしか望んでいないのですか? –

答えて

1

私が正しくあなたを理解していれば、あなたが何かしたい:私たちは機能を少し変更するとタグを生成する場合

look_through_structure(parent, my_tag): 
    for node in parent.iter("*"): 
     out_str.write('Parent tag: %s\n' % node.tag) 
     for nxt in node: 
      if nxt.tag == my_tag: 
       out_str.write('child tag: %s\n' % my_tag) 
       return 
      out_str.write('Parent tag: %s\n' % nxt.tag) 
      if any(ch.tag == my_tag for ch in nxt.getchildren()): 
       out_str.write('child tag: %s\n' % my_tag) 
       return 

を:

def look_through_structure(parent, my_tag): 
    for node in parent.iter("*"): 
     yield node.tag 
     for nxt in node: 
      if nxt.tag == my_tag: 
       yield nxt.tag 
       return 
      yield nxt.tag 
      if any(ch.tag == my_tag for ch in nxt.getchildren()): 
       yield my_tag 
       return 

そして、ファイル上でそれを実行します。

In [24]: root = tree.getroot() 

In [25]: my_tag = 'neighbor' 

In [26]: list(look_through_structure(root, my_tag)) 
Out[26]: ['data', 'country', 'neighbor'] 

また、完全なパスが必要な場合は、lxmlのgetpathがこれを行います。

import lxml.etree as ET 

tree = ET.parse('country.xml') 

my_tag = 'neighbor' 

print(tree.getpath(tree.find(".//neighbor"))) 

出力:

/data/country[1]/neighbor[1] 
1

@Padraic。どうもありがとう!あなたのコードは主に私が望むものです。私は、隣接ノードのための国のノードと親の子である(例えば、属性のために)追加のノードを挿入した場合しかし、それは予期しない結果が得られます。

<data> 
<country name="Liechtenstein"> 
<attributes> 
    <rank>1</rank> 
    <year>2008</year> 
    <gdppc>141100</gdppc> 
    <neighbor name="Austria" direction="E"/> 
    <neighbor name="Switzerland" direction="W"/> 
    </attributes> 
</country> 
<country name="Singapore"> 
<attributes> 
    <rank>4</rank> 
    <year>2011</year> 
    <gdppc>59900</gdppc> 
    <neighbor name="Malaysia" direction="N"/> 
    </attributes> 
</country> 
<country name="Panama"> 
<attributes> 
    <rank>68</rank> 
    <year>2011</year> 
    <gdppc>13600</gdppc> 
    <neighbor name="Costa Rica" direction="W"/> 
    <neighbor name="Colombia" direction="E"/> 
    </attributes> 
</country> 

はとにかくあなたの助けが非常にfruitfullました。私はあなたのコードを取得し、これを作成します。

import lxml.etree as et 
root = et.parse('country_data.xml') 

out_f = open('getpath.txt', 'w') 

my_str1 = 'country[1]' 
my_str2 = 'neighbor[1]' 

for e in root.iter(): 
    s = root.getelementpath(e) 
    if my_str1 not in s: 
     continue 
    if my_str2 not in s: 
     continue 
    out_f.write('%s\n' %(s)) 
    break 
out_f.close() 

考え方は単純です:elementpathは、文字列「国」と「隣人」を持っている場合には、出力ファイルにダウンwritedされます。元のxmlの例では、country [1]/neighbor [1]となります。追加の親を持つxmlの場合は、country [1]/attributes/neighbor [1]となります。

関連する問題