如何使用Python迭代XML(使用XML .dom.minidom)来测试子节点是否存在



我使用Python和xml.dom。minidom,迭代导出的Excel电子表格,为我们的食堂菜单输出一个HTML表,其中包含对.write的各种调用。困难在于Excel输出的XML不是结构化的。为了弥补这一点,我设置了许多变量(day, previousDay, meal等),当我遇到具有我正在测试的nodeValue的子节点时,这些变量会被设置。我有一堆if语句来确定何时启动一个新表(对于一周中的每一天),或者何时启动一个新行(当day != previousDay)等等。

我很难弄清楚如何忽略特定的节点。有几个节点从Excel中获得输出,我需要忽略,我可以根据它们的子节点具有特定的值来做到这一点,但我不知道如何实现它。

基本上,我需要在我的主for循环中使用下面的if语句:
for node in dome.getElementsByTagName('data'):  
    if node contains childNode with nodeValue == 'test':
        do something

我很快倾向于使用一个嵌套的for循环,其中包含一个get-out- node-free-card(嗯,异常),就像下面这样。

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

一定要用xml.dom.minidom吗?因为这正是XPath所擅长的。例如,使用lxml.etree,可以找到所需的所有元素:

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

W3C的DOM很难用于解决实际问题,因为它不包括返回元素值的属性之类的简单内容。(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"))

您考虑过使用SAX解析器吗?Sax解析器按照节点的出现顺序(深度优先)处理XML树结构,并允许您在解析节点值时处理节点值。

xml.sax.XmlReader

最新更新