【问题标题】:Problem with recursive search of xml document using python使用python递归搜索xml文档的问题
【发布时间】:2009-07-21 07:41:22
【问题描述】:

我正在尝试编写一个函数,它将接受一个 xml 对象,任意数量的标签,由包含标签名称、属性和属性值的元组定义(例如 ('tag1', 'id', '1') ) 并尽可能返回最具体的节点。我的代码如下:

from xml.dom import minidom

def _search(object, *pargs):
    if len(pargs) == 0:
        print "length of pargs was zero"
        return object
    else:
        print "length of pargs is %s" % len(pargs)
    if pargs[0][1]:
        for element in object.getElementsByTagName(pargs[0][0]):
            if element.attributes[pargs[0][1]].value == pargs[0][2]:
                _search(element, *pargs[1:])
    else:
        if object.getElementsByTagName(pargs[0][0]) == 1:
            _search(element, *pargs[1:])
def main():
    xmldoc = minidom.parse('./example.xml')
    tag1 = ('catalog_item', 'gender', "Men's")
    tag2 = ('size', 'description', 'Large')
    tag3 = ('color_swatch', '', '')

    args = (tag1, tag2, tag3)
    node = _search(xmldoc, *args)
    node.toxml()
if __name__ == "__main__":
    main()

不幸的是,这似乎不起作用。这是我运行脚本时的输出:

$ ./secondsearch.py
length of pargs is 3
length of pargs is 2
length of pargs is 1
Traceback (most recent call last):
  File "./secondsearch.py", line 35, in <module>
    main()
  File "./secondsearch.py", line 32, in main
    node.toxml()
AttributeError: 'NoneType' object has no attribute 'toxml'

为什么不执行 'if len(pargs) == 0' 子句?如果我确实设法将 xml 对象返回给我的 main 方法,那么我可以将该对象传递给其他一些函数(这可能会更改节点的值,或附加子节点等)吗?

背景:使用python自动化测试流程,环境是winxp/vista/7上的cygwin,python版本是2.5.2。如果可能的话,我更愿意留在标准库中。

这是工作代码

def _search(object, *pargs):
    if len(pargs) == 0:
        print "length of pargs was zero"
    else:
        print "length of pargs is %s" % len(pargs)
    for element in object.getElementsByTagName(pargs[0][0]):
        if pargs[0][1]:
            if element.attributes[pargs[0][1]].value == pargs[0][2]:
                return _search(element, *pargs[1:])
        else:
            if object.getElementsByTagName(pargs[0][0]) == 1:
                return _search(element, *pargs[1:])
    return object

【问题讨论】:

  • 你的代码好像被扁平化了;您可能应该修复它,以便人们可以运行它。

标签: python xml


【解决方案1】:

我假设您使用 http://www.eggheadcafe.com/community/aspnet/17/10084853/xml-viewer.aspx 作为您的示例数据...

作为Vinay pointed out,您不会从对_search 的递归调用中返回任何内容。

在您的 else 情况下,您不定义元素的值,而是将其传递给 _search()

此外,如果 pargs[0][1] 为空,则您不执行任何操作,但 object.getElementsByTagName(pargs[0][0]) 返回多个节点...(这也是您的 pargs == 0 案例永远不会被命中的原因...)

毕竟,如果样本数据正确,则有两个匹配节点。所以你会有一个 NodeList 包含:

        <color_swatch image="red_cardigan.jpg">Red</color_swatch>
        <color_swatch image="burgundy_cardigan.jpg">Burgundy</color_swatch>

你不能在 NodeList 上调用 .toxml()...

【讨论】:

  • 谢谢。您提出了几个有效的观点,我在重写函数时牢记了所有这些观点。代码本身中唯一没有表示的是处理返回的 NodeList 的部分 - 在我的脚本中得到了一条注释,提醒我包含足够的信息来获取特定节点。
【解决方案2】:

您不应该在递归调用 _search 之前插入 return 吗?按照您现在的方式,_search 的某些退出路径没有 return 语句,因此它们将返回 None - 这会导致您看到的异常。

【讨论】:

  • 我不确定您所说的“在递归调用之前插入返回”是什么意思,特别是“在前面”。你能更全面地解释一下吗?
  • 是的 - 你的语句应该是 return _search(element, *pargs[1:]) 而不仅仅是 _search(element, *pargs[1:])
  • 感谢您的澄清。我给 Stobor 提供了解决方案,但我提高了你的分数以反映你的重要帮助。再次感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-02-24
  • 1970-01-01
  • 1970-01-01
  • 2012-08-04
  • 1970-01-01
  • 1970-01-01
  • 2022-01-22
相关资源
最近更新 更多