2015-02-04 1 views
0

У меня возникают две проблемы с разбором XML-файла. Я хочу только вернуть один набор свойств I.E только значения свойств в первом Процессе, и я хочу вернуть второй Источник во втором Процессе. Когда я использую свой код, он возвращает Source в первых источниках и первом источнике во втором источнике, но я не могу получить второй источник для возврата.Разбор XML-файла с использованием ElementTree

файл XML выглядит следующим образом:

<!-- The description of the process --> 
<Description>"This is a description"</Description> 

<!-- info on process to be run --> 
<Process expectFailure="false"> 
    <Code>Import</Code> 
    <Sources> 
     <Source>"Test Data"</Source> 
    </Sources> 
    <Destination>Buffered</Destination> 
    <Properties> 
     <Property code="format" value="CC"/> 
     <Property code="Input" value="10N"/> 
     <Property code="Method" value="BASIC"/> 
     <Ppoperty code="Resolution" value="5"/> 
     <Property code="Convention" value="LEFT"/> 
     <Property code="Bounding" value="BUFFERED"/> 
    </Properties> 
</Process> 

<!-- info on second process to be run (compare) --> 
<Process> 
    <Code>SurfaceCompare</Code> 
    <Sources> 
     <Source>expectedOutput</Source> 
     <Source>Buffered</Source> 
    </Sources> 
    <Properties> 
     <Property code="compare_designated" value="true"/> 
     <Property code="compare_metadata" value="true"/> 
     <Property code="metadata_type" value="OTHER"/> 
    </Properties> 
</Process> 

и код выглядит

from xml.etree import ElementTree 

tree = ElementTree.parse("XML_example.xml") 

description = tree.findtext("Description") 
print(description) 

for process in tree.findall('Process'): 
    for source in process.findall('Sources'): 
     source_text = source.findtext('Source') 
     print(source_text) 

#returns everything 
for property in process.iter('Property'): 
    print(property.attrib.get('code')) 
    print(property.attrib.get('value')) 

for process in tree.findall('Process'): 
    for source in process.findall('Sources'): 
     source = source.findtext('Source') 
     print(source) 

Я пробовал много различных способов использования findall, find, iter, get, getiter. Я уверен, что у меня что-то не хватает, но это был долгий день, и для меня жизнь я не вижу, чего не хватает.

Существует также возможность изменить способ создания XML, но я знаю, что должен быть способ решить этот вопрос, и он грызет меня.

Пример надлежащего вывода для источников:

"Test Data" 
expectedOutput 
buffered 

Образец Надлежащий вывод 1 для свойств:

format 
CC 
Input 
10N 
Method 
BASIC 
Convention 
LEFT 
Bounding 
BUFFERED 

Образец Надлежащий вывод 2:

compare_designated 
true 
compare_metadata 
true 
metadata_type 
OTHER 

ответ

1

Самый простой способ добиться того, что вы хотите использовать find или findall с путь, ИТЭРА хорошо работает с тегом имени, но в вашем случае, используя путь будет более подходящими.

Вот один из способов сделать это, кстати, ваш образец отсутствует корневой элемент, таким образом, я добавил в мой код:

import xml.etree.ElementTree as ET 
from StringIO import StringIO 

s = '''<!-- The description of the process --> 
<Description>"This is a description"</Description> 

<!-- info on process to be run --> 
<Process expectFailure="false"> 
    <Code>Import</Code> 
    <Sources> 
     <Source>"Test Data"</Source> 
    </Sources> 
    <Destination>Buffered</Destination> 
    <Properties> 
     <Property code="format" value="CC"/> 
     <Property code="Input" value="10N"/> 
     <Property code="Method" value="BASIC"/> 
     <Ppoperty code="Resolution" value="5"/> 
     <Property code="Convention" value="LEFT"/> 
     <Property code="Bounding" value="BUFFERED"/> 
    </Properties> 
</Process> 

<!-- info on second process to be run (compare) --> 
<Process> 
    <Code>SurfaceCompare</Code> 
    <Sources> 
     <Source>expectedOutput</Source> 
     <Source>Buffered</Source> 
    </Sources> 
    <Properties> 
     <Property code="compare_designated" value="true"/> 
     <Property code="compare_metadata" value="true"/> 
     <Property code="metadata_type" value="OTHER"/> 
    </Properties> 
</Process>''' 

# once you've parsed the file, you need to **getroot()** 
tree = ET.parse(StringIO('<root>' + s + '</root>')).getroot() 

Например, вы можете использовать путь для получения первого Процесс [1] -> Свойства -> Свойство, используя findall, вы можете получить для всех Свойство узлов и повторить их:

# and iterate all Property nodes, and get their attributes like this 
for p in tree.findall('./Process[1]/Properties/Property'): 
    print p.attrib # to get code/value, use p.attrib.get('code') etc. 

Таким образом, вы получите первые процесса/Свойства и все атрибуты недвижимости «s:

{'code': 'format', 'value': 'CC'} 
{'code': 'Input', 'value': '10N'} 
{'code': 'Method', 'value': 'BASIC'} 
{'code': 'Convention', 'value': 'LEFT'} 
{'code': 'Bounding', 'value': 'BUFFERED'} 

Другой пример, чтобы получить только второй процесса, второй Источник текст , используя путь довольно прямолинейный с find тоже:

print tree.find('./Process[2]/Sources/Source[2]').text 
Buffered 

Я надеюсь, что вы получите представление о том, как использовать их, помните, чтобы получить один узел вы используете find, чтобы возвращать список узлов, вы используете findall, надеюсь, что это помогает.

+0

Спасибо. У меня нет времени попробовать сейчас, но это выглядит многообещающе. Попробуй, когда я вернусь домой. – erics12512354

+0

@ erics12512354, не беспокойтесь, не торопитесь, и я уверен, что как только вы поймете, как работает ** путь **, у вас возникнет проблема с решением проблемы. – Anzel

+1

Работает. Я не понимал, что вы можете добавить позиционные аргументы в пути к файлам, и мне не хватало ./, и когда я это пробовал. Еще раз спасибо. – erics12512354