【问题标题】:Python XML Parsing without root没有root的Python XML解析
【发布时间】:2014-07-16 11:26:52
【问题描述】:

我想解析一个相当大的类似 xml 的文件,它没有任何根元素。文件格式为:

<tag1>
<tag2>
</tag2>
</tag1>

<tag1>
<tag3/>
</tag1>

我尝试了什么:

  1. 尝试使用 ElementTree 但它返回“无根”错误。 (有没有其他的python库可以用来解析这个文件?)
  2. 尝试添加一个额外的标签来包装整个文件,然后使用 Element-Tree 对其进行解析。但是,我想使用一些更有效的方法,我不需要更改原始 xml 文件。

【问题讨论】:

  • 文件有多大?
  • 它包含超过 300 万个有用的术语(除了标签和其他不必要的数据)
  • 大概的文件大小?您在寻找时间效率还是内存效率?可以将整个文件读入内存吗?

标签: python xml parsing python-2.7 elementtree


【解决方案1】:

lxml.html 可以解析片段

from lxml import html
s = """<tag1>
 <tag2>
 </tag2>
</tag1>

<tag1>
 <tag3/>
</tag1>"""
doc = html.fromstring(s)
for thing in doc:
    print thing
    for other in thing:
        print other
"""
>>> 
<Element tag1 at 0x3411a80>
<Element tag2 at 0x3428990>
<Element tag1 at 0x3428930>
<Element tag3 at 0x3411a80>
>>>
"""

礼貌this SO answer

如果有不止一层嵌套:

def flatten(nested):
    """recusively flatten nested elements

    yields individual elements
    """
    for thing in nested:
        yield thing
        for other in flatten(thing):
            yield other
doc = html.fromstring(s)
for thing in flatten(doc):
    print thing

同样,lxml.etree.HTML 会解析这个。它添加了 html 和 body 标签:

d = etree.HTML(s)
for thing in d.iter():
    print thing

""" 
<Element html at 0x3233198>
<Element body at 0x322fcb0>
<Element tag1 at 0x3233260>
<Element tag2 at 0x32332b0>
<Element tag1 at 0x322fcb0>
<Element tag3 at 0x3233148>
"""

【讨论】:

    【解决方案2】:

    ElementTree.fromstringlist 接受一个可迭代对象(产生字符串)。

    itertools.chain一起使用:

    import itertools
    import xml.etree.ElementTree as ET
    # import xml.etree.cElementTree as ET
    
    with open('xml-like-file.xml') as f:
        it = itertools.chain('<root>', f, '</root>')
        root = ET.fromstringlist(it)
    
    # Do something with `root`
    root.find('.//tag3')
    

    【讨论】:

    • 我想这在大文件的情况下不是一种有效的方法。同样正如我之前所说,我想使用不同的方法来实现这一点,而不是在输入中添加标签。
    • @sgp,我应该写f 而不是f.read()。更新。;至少这不会一次读取全部内容。
    • 您不认为使用不同的库会更好吗?我的意思是,您只是在向 xml 添加额外的标签,对吗?你能解释一下为什么你认为你的方法是有效的吗?谢谢:)
    • @sgp,因为这不会像我在之前的评论中所说的那样一次加载全部内容。我没有对解决方案进行基准测试;我不能说哪一个表现更好。 (顺便说一句,试试cElementTree 而不是ElementTree
    【解决方案3】:

    与其编辑文件,不如做这样的事情

    import xml.etree.ElementTree as ET
    
    with file("xml-file.xml") as f:
        xml_object = ET.fromstringlist(["<root>", f.read(), "</root>"])
    

    【讨论】:

    • 在我的问题中,我说过我已经尝试过这个,我想要一个比那个更好的方法。由于文件足够大,您建议的方法效率不高。
    • @sgp 你说你编辑了原始文件。这不是这样做的。 我想使用一些更有效的方法,我不需要改变原始的xml文件 ...原始文件没有改变。
    • 在实践中,两者是相同的方法,不是吗?您基本上将额外的标签添加到字符串中。我宁愿有一个不给出“无根错误”的库。这种方法不是很好,因为文件很大,给字符串添加标签的过程会花费一些时间,从而导致效率低下。
    • @sgp 查看我更新的答案我知道更长的编辑字符串。这比编辑感觉更有效。我只写入内存而不写入磁盘。
    • @sgp - 在这个和 falsetru 的解决方案中添加两个标签是微不足道的。 on-the-fly 添加它们 - 文件内容没有额外的迭代,它没有使用添加的标签构造一个完整的新字符串。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-07
    • 2019-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多