Чтение XML с использованием Python minidom и итерация по каждому узлу - PullRequest
24 голосов
/ 11 сентября 2009

У меня есть структура XML, которая выглядит следующим образом, но в гораздо большем масштабе:

<root>
    <conference name='1'>
        <author>
            Bob
        </author>
        <author>
            Nigel
        </author>
    </conference>
    <conference name='2'>
        <author>
            Alice
        </author>
        <author>
            Mary
        </author>
    </conference>
</root>

Для этого я использовал следующий код:

dom = parse(filepath)
conference=dom.getElementsByTagName('conference')
for node in conference:
    conf_name=node.getAttribute('name')
    print conf_name
    alist=node.getElementsByTagName('author')
    for a in alist:
        authortext= a.nodeValue
        print authortext

Однако авторский текст, который распечатывается, - «Нет». Я попытался возиться с использованием вариантов, как показано ниже, но это приводит к сбою моей программы.

authortext=a[0].nodeValue

Правильный вывод должен быть:

1
Bob
Nigel
2
Alice
Mary

Но я получаю:

1
None
None
2
None
None

Любые предложения о том, как решить эту проблему?

Ответы [ 5 ]

23 голосов
/ 11 сентября 2009

ваш authortext имеет тип 1 (ELEMENT_NODE), обычно вам нужно иметь TEXT_NODE для получения строки. Это будет работать

a.childNodes[0].nodeValue
6 голосов
/ 11 сентября 2009

Узлы элемента не имеют значения nodeValue. Вы должны посмотреть на узлы Text внутри них. Если вы знаете, что внутри всегда есть один текстовый узел, вы можете сказать element.firstChild.data (данные такие же, как nodeValue для текстовых узлов).

Будьте осторожны: если текстового содержимого нет, дочерних текстовых узлов не будет, а element.firstChild будет иметь значение NULL, что приведет к сбою доступа .data.

Быстрый способ получения содержимого прямых дочерних текстовых узлов:

text= ''.join(child.data for child in element.childNodes if child.nodeType==child.TEXT_NODE)

В DOM Level 3 Core вы получаете свойство textContent, которое вы можете использовать для рекурсивного получения текста внутри элемента, но minidom не поддерживает это (некоторые другие реализации Python DOM делают).

2 голосов
/ 06 сентября 2013

Быстрый доступ:

node.getElementsByTagName('author')[0].childNodes[0].nodeValue
1 голос
/ 09 февраля 2016

Поскольку у вас всегда есть одно значение текстовых данных на автора, вы можете использовать element.firstChild.data

dom = parseString(document)
conferences = dom.getElementsByTagName("conference")

# Each conference here is a node
for conference in conferences:
    conference_name = conference.getAttribute("name")
    print 
    print conference_name.upper() + " - "

    authors = conference.getElementsByTagName("author")
    for author in authors:
        print "  ", author.firstChild.data
    # for

    print
0 голосов
/ 11 сентября 2009

Я немного поиграл с этим, и вот что я получил на работу:

# ...
authortext= a.childNodes[0].nodeValue
print authortext

приводит к выводу:

C:\temp\py>xml2.py
1
Bob
Nigel
2
Alice
Mary

Я не могу точно сказать, зачем вам нужен дочерний узел, чтобы получить внутренний текст, но по крайней мере это то, что вы искали.

...