2017-02-09 5 views
1

Я пытаюсь изучить Python, написав скрипт, который будет извлекать данные из нескольких записей в файле XML. Мне удалось найти ответы на большинство моих вопросов путем поиска в Интернете, но я не нашел способа определить, не содержит ли тег XML никаких данных перед getElementsByTagName («tagname») [0] .firstChild используется метод .data, и при отсутствии данных присутствует атрибут AttributeError. Я понимаю, что я мог написать свой код с помощью try и обработать AttributeError, но я бы предпочел знать, что тег пуст, прежде чем я попытаюсь извлечь данные, которые не должны обрабатывать исключение. Вот пример XML-файла, который содержит две записи с данными в тегах и одну с пустым тегом.Использование Python 3.6 для анализа XML, как я могу определить, не содержит ли тег XML

<?xml version='1.0' encoding='UTF-8' standalone='yes' ?> 
<records> 
    <rec> 
    <name>ZYSRQPO</name> 
    <state>Washington</state> 
    <country>United States</country> 
    </rec> 
    <rec> 
    <name>ZYXWVUT</name> 
    <state></state> 
    <country>Mexico</country> 
    </rec> 
</records> 

Вот пример кода, который я мог бы использовать для извлечения данных:

from xml.dom import minidom 
import sys 

mydoc = minidom.parse('mydataFile.xml') 
records = mydoc.getElementsByTagName("rec") 

for rec in records: 
    try: 
     name = rec.getElementsByTagName("name")[0].firstChild.data 
     state = rec.getElementsByTagName("state")[0].firstChild.data 
     country = rec.getElementsByTagName("country")[0].firstChild.data 
     print('{}\t{}\t{}'.format(name, state, country)) 

    except (AttributeError): 
     print('AttributeError encountered in record {}'.format(name), file=sys.stderr) 
     continue 

При обработке этого файла нет информации для записи имени ZYXWVUT будет распечатана за исключением того, что исключение встречалось , Я хотел бы иметь нулевое значение для используемого имени состояния, а остальную информацию, напечатанную об этой записи. Есть ли метод, который можно использовать для выполнения того, что я хочу, чтобы я мог использовать оператор if, чтобы определить, не содержит ли тег никаких данных перед использованием getElementsByTagName и встречается ошибка, когда данные не найдены?

ответ

1
from xml.dom import minidom 
import sys 

mydoc = minidom.parse('mydataFile.xml') 
records = mydoc.getElementsByTagName("rec") 

for rec in records: 
    name = rec.getElementsByTagName("name")[0].firstChild.data 
    state = None if len(rec.getElementsByTagName("state")[0].childNodes) == 0 else rec.getElementsByTagName("state")[0].firstChild.data 
    country = rec.getElementsByTagName("country")[0].firstChild.data 
    print('{}\t{}\t{}'.format(name, state, country)) 

Или, если есть какой-то шанс, что имя и страна пусто тоже:

from xml.dom import minidom 
import sys 


def get_node_data(node): 
    if len(node.childNodes) == 0: 
     result = None 
    else: 
     result = node.firstChild.data 
    return result 


mydoc = minidom.parse('mydataFile.xml') 
records = mydoc.getElementsByTagName("rec") 

for rec in records: 
    name = get_node_data(rec.getElementsByTagName("name")[0]) 
    state = get_node_data(rec.getElementsByTagName("state")[0]) 
    country = get_node_data(rec.getElementsByTagName("country")[0]) 
    print('{}\t{}\t{}'.format(name, state, country)) 
+0

Спасибо, я ценю ваш ответ. Мне особенно нравится второе предложение, хотя мало шансов, что ни имя, ни страна никогда не будут пустыми, это приведет к более элегантному поиску структуры. У меня есть где-то еще, что мне нужно быть прямо сейчас, поэтому я не пробовал это, но попробую, как только смогу. – JCB

0

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

from xml.dom import minidom 
import sys 

def get_node_data(node): 
    if len(node.childNodes) == 0: 
     result = '*->No ' + node.nodeName + '<-*' 
    else: 
     result = node.firstChild.data 
    return result 

mydoc = minidom.parse(dataFileSpec) 
records = mydoc.getElementsByTagName("rec") 

for rec in records: 
    name = get_node_data(rec.getElementsByTagName("name")[0]) 
    state = get_node_data(rec.getElementsByTagName("state")[0]) 
    country = get_node_data(rec.getElementsByTagName("country")[0]) 
    print('{}\t{}\t{}'.format(name, state, country)) 

Когда это будет работать против этого XML:

<?xml version='1.0' encoding='UTF-8' standalone='yes' ?> 
<records> 
    <rec> 
    <name>ZYSRQPO</name> 
    <country>United States</country> 
    <state>Washington</state> 
    </rec> 
    <rec> 
    <name></name> 
    <country>United States</country> 
    <state>Washington</state> 
    </rec> 
    <rec> 
    <name>ZYXWVUT</name> 
    <country>Mexico</country> 
    <state></state> 
    </rec> 
    <rec> 
    <name>ZYNMLKJ</name> 
    <country></country> 
    <state>Washington</state> 
    </rec> 
</records> 

Он производит этот выход:

ZYSRQPO Washington  United States 
*->No name<-* Washington  United States 
ZYXWVUT *->No state<-* Mexico 
ZYNMLKJ Washington  *->No country<-* 
Смежные вопросы