我使用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