2016-06-24 1 views
1

Я новичок в этом. Из-за моего первоначального xml около 8 ГБ трудно изучить всех родителей, бабушек и дедушек, грандов и пр. Для заинтересованного ребенка в оригинальном xml вручную. Я пытаюсь просмотреть все узлы, пока не будет найден заинтересованный ребенок. Поэтому я хочу создать структуру «скелета» xml до интересующего ребенка country_data.xml отсюда https://docs.python.org/2/library/xml.etree.elementtree.html. Извините за код:Как создать структуру xml до определенного узла xml ussing Python?

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 всех узловых тегов:

родительских тег: Родитель данные тегов: страна Parent тега: ранг Parent тег: год Родителя тег: gdppc ребенка тег : сосед родительский тег: страна родитель тег: ранг родитель тег: год родительский тег: gdppc Детский тег: сосед родитель тег: страна родитель тег: ранг родитель тег: год родительский тег: gdppc Детский тег: сосед

Но я хочу что-то подобное (мой заинтересован ребенок "сосед"): данные

    • страна
      • сосед

Или что:/dat а/страна/сосед. Что не так?

+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's 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> 

В любом случае ваша помощь была очень плодородная. Я беру свой код и создать этот один:

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]/neighbour [1]. А для xml с дополнительным родителем он дает: country [1]/attributes/neighbour [1].