Как проверить наличие дочерних узлов, используя Python для итерации по XML (используя xml.dom.minidom) - PullRequest
2 голосов
/ 07 апреля 2011

Я использую Python и xml.dom.minidom для перебора экспортированной электронной таблицы Excel, выводя таблицу HTML для нашего меню столовой с различными вызовами .write. Трудность заключается в том, что XML, который выводит Excel, не структурирован. Чтобы компенсировать это, я настроил ряд переменных (день, предыдущий день, прием пищи и т. Д.), Которые устанавливаются, когда я сталкиваюсь с дочерними узлами, у которых есть значение узла, с которым я тестирую. У меня есть куча операторов if, чтобы определить, когда начинать новую таблицу (для каждого дня недели) или новую строку (когда день! = Предыдущий день) и так далее.

Мне трудно понять, как игнорировать отдельные узлы. Есть несколько узлов, которые получают выходные данные из Excel, которые мне нужно игнорировать, и я могу сделать это на основе их дочерних узлов, имеющих определенные значения, но я не могу понять, как это реализовать.

По сути, мне нужно следующее выражение if в моем цикле main:

for node in dome.getElementsByTagName('data'):  
    if node contains childNode with nodeValue == 'test':
        do something

Ответы [ 3 ]

0 голосов
/ 07 апреля 2011

Вы должны использовать xml.dom.minidom?Потому что это та вещь, в которой сияет XPath.Например, используя lxml.etree, можно найти все нужные элементы:

my_elements = document.xpath("//data[not(*[.='test'])]")

DOM W3C действительно трудно использовать для реальных задач, поскольку он не включает в себя простые вещи, такие какатрибут, возвращающий значение элемента.(XPath объявляет, что значением элемента являются все его дочерние текстовые узлы, соединенные вместе, поэтому вышеприведенный шаблон работает.)

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

def element_text(e):
  return "".join(t.nodeValue for t in e.childNodes if t.nodeType == Node.TEXT_NODE)

Это упрощает создание функции фильтра, например:

def element_is_of_interest(e):
   return not any((c for c in e.childNodes if element_text(c) == "test"))

, и вы получаете такие элементы следующим образом:

my_elements = filter(element_is_of_interest, d.getElementsByTagName("data"))
0 голосов
/ 18 августа 2011

Рассматривали ли вы вместо этого парсер SAX? Sax-парсеры обрабатывают структуру дерева XML в порядке появления узлов (сначала глубина) и позволяют вам обрабатывать значение узла в точке его синтаксического анализа.

xml.sax.XmlReader

0 голосов
/ 07 апреля 2011

Мое быстрое склонение - иметь вложенный цикл for с карточкой get-out-of-node-free (гм, исключение), как показано ниже.

Class BadNodeException (Exception):
pass
for node in dome.getElementsByTagName('data'):
try:  
    for child in node.childNodes:
        if child.nodeValue == 'test':
           raise BadNodeException
    ## process node as normal
except BadNodeException:
    pass
...