【问题标题】:Find element with attribute with minidom查找具有 minidom 属性的元素
【发布时间】:2010-03-10 07:11:21
【问题描述】:

给定

<field name="frame.time_delta_displayed" showname="Time delta from previous displayed frame: 0.000008000 seconds" size="0" pos="0" show="0.000008000"/>
<field name="frame.time_relative" showname="Time since reference or first frame: 0.000008000 seconds" size="0" pos="0" show="0.000008000"/>
<field name="frame.number" showname="Frame Number: 2" size="0" pos="0" show="2"/>
<field name="frame.pkt_len" showname="Packet Length: 1506 bytes" hide="yes" size="0" pos="0" show="1506"/>
<field name="frame.len" showname="Frame Length: 1506 bytes" size="0" pos="0" show="1506"/>
<field name="frame.cap_len" showname="Capture Length: 1506 bytes" size="0" pos="0" show="1506"/>
<field name="frame.marked" showname="Frame is marked: False" size="0" pos="0" show="0"/>
<field name="frame.protocols" showname="Protocols in frame: eth:ip:tcp:http:data" size="0" pos="0" show="eth:ip:tcp:http:data"/>

如何在不遍历每个标签并检查属性的情况下立即获取 name="frame.len" 的字段?

【问题讨论】:

  • 添加到这个问题,xml是300mb。上次我尝试解析它时内存不足。有更好的萨克斯风格库的建议吗?
  • 嗯,xml.dom.minidom 是一个 DOM 解析器,需要将整个文档读入内存。不是因为它不够好,而是因为 DOM 解析器就是这样做的。所以我不知道你所说的“更好的萨克斯风格库”是什么意思。 xml.sax 这个 Python 自带的标准 SAX 解析器有什么不好?
  • 在 5000 个数据包 (300mb) 之后,尝试加载 xml 会使我的计算机崩溃。在这 300mb 的数据中,我只需要大约 10kb 分布在整个文档中。有没有比lxml更高效的xml遍历方式和比sax更简单的库?

标签: python xml minidom


【解决方案1】:

我不认为你可以。

来自父element,你需要

for subelement in element.GetElementsByTagName("field"):
    if subelement.hasAttribute("frame.len"):
        do_something()

响应您从 3 月 11 日开始的评论,如果您的文档结构稳定且没有令人讨厌的意外(例如属性中的尖括号),您可能想尝试不可思议的事情并使用正则表达式。这不是推荐的做法,但可以工作并且比实际解析文件要容易得多。我承认我自己有时也这样做过。还没有失明。

所以在你的情况下你可以(假设&lt;field&gt; 标签不跨越多行):

xmlfile = open("myfile.xml")
for line in xmlfile:
    match = re.search(r'<field\s+name="frame.len"\s+([^>]+)/>', line):
    if match:
        result = match.group(1)
        do_something(result)

如果&lt;field&gt; 标签可以跨越多行,您可以尝试将整个文件作为纯文本加载到内存中,然后扫描它以查找匹配项:

filedump = open("myfile.xml").read()
for match in re.finditer(r'<field\s+name="frame.len"\s+([^>]+)/>', filedump):
    result = match.group(1)
    do_something(result)

在这两种情况下,result 将包含frame.len 以外的属性。正则表达式假定frame.len 始终是标签内的第一个属性。

【讨论】:

    【解决方案2】:

    你没有——DOM API,设计有点糟糕(由 w3c,而不是由 Python!-)没有这样的搜索功能来为你进行迭代。要么接受循环的需要(一般不是通过每个标签,而是通过所有具有给定标签名称的标签),或者升级到更丰富的界面,例如BeautifulSouplxml

    【讨论】:

      【解决方案3】:

      哇,那个正则表达式太可怕了!截至 2016 年,每个 DOMElement 都有一个 .getAttribute() 方法,这使事情变得更容易一些,但您仍然需要遍历元素。

      l = []
      for e in elements:
          if e.hasAttribute('name') and e.getAttribute('name') == 'field.len':
              l.append(e)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-01-15
        • 1970-01-01
        • 2013-07-03
        • 2021-10-19
        • 1970-01-01
        • 1970-01-01
        • 2021-10-06
        • 2013-02-04
        相关资源
        最近更新 更多