首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >ElementTree迭代解析策略

ElementTree迭代解析策略
EN

Stack Overflow用户
提问于 2012-10-09 12:51:47
回答 2查看 28.6K关注 0票数 24

我必须处理足够大(最大1 1GB)的xml文档,并用python解析它们。我使用了iterparse()函数(SAX风格的解析)。

我关心的问题如下,假设您有一个这样的xml

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8" ?>
<families>
  <family>
    <name>Simpson</name>
    <members>
        <name>Homer</name>
        <name>Marge</name>
        <name>Bart</name>
    </members>
  </family>
  <family>
    <name>Griffin</name>
    <members>
        <name>Peter</name>
        <name>Brian</name>
        <name>Meg</name>
    </members>
  </family>
</families>

当然,问题是要知道我什么时候会得到一个姓氏(如辛普森),以及我什么时候会得到某个家庭成员的名字(例如荷马)。

到目前为止,我所做的是使用"switches“,它将告诉我我是否在"members”标记内,代码将如下所示

代码语言:javascript
复制
import xml.etree.cElementTree as ET

__author__ = 'moriano'

file_path = "test.xml"
context = ET.iterparse(file_path, events=("start", "end"))

# turn it into an iterator
context = iter(context)
on_members_tag = False
for event, elem in context:
    tag = elem.tag
    value = elem.text
    if value :
        value = value.encode('utf-8').strip()

    if event == 'start' :
        if tag == "members" :
            on_members_tag = True

        elif tag == 'name' :
            if on_members_tag :
                print "The member of the family is %s" % value
            else :
                print "The family is %s " % value

    if event == 'end' and tag =='members' :
        on_members_tag = False
    elem.clear()

这可以很好地工作,因为输出是

代码语言:javascript
复制
The family is Simpson 
The member of the family is Homer
The member of the family is Marge
The member of the family is Bart
The family is Griffin 
The member of the family is Peter
The member of the family is Brian
The member of the family is Meg

我担心的是,在这个(简单的)示例中,我必须创建一个额外的变量来知道我在哪个标记中(on_members_tag)想象一下我必须处理的真正的xml示例,它们有更多的嵌套标记。

另请注意,这是一个非常简化的示例,因此您可以假设我面对的xml可能包含更多标记、更多内部标记,并试图获取不同的标记名、属性等。

所以问题是。我是不是做了什么非常愚蠢的事?我觉得必须有一个更优雅的解决方案。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-10-09 14:24:36

这里有一种可能的方法:我们维护一个路径列表,并向后查看以找到父节点。

代码语言:javascript
复制
path = []
for event, elem in ET.iterparse(file_path, events=("start", "end")):
    if event == 'start':
        path.append(elem.tag)
    elif event == 'end':
        # process the tag
        if elem.tag == 'name':
            if 'members' in path:
                print 'member'
            else:
                print 'nonmember'
        path.pop()
票数 33
EN

Stack Overflow用户

发布于 2012-10-09 15:24:15

pulldom在这方面做得很好。您会得到一个sax流。您可以遍历流,当找到您感兴趣的节点时,将该节点加载到dom片段中。

代码语言:javascript
复制
import xml.dom.pulldom as pulldom
import xpath # from http://code.google.com/p/py-dom-xpath/

events = pulldom.parse('families.xml')
for event, node in events:
    if event == 'START_ELEMENT' and node.tagName=='family':
        events.expandNode(node) # node now contains a dom fragment
        family_name = xpath.findvalue('name', node)
        members = xpath.findvalues('members/name', node)
        print('family name: {0}, members: {1}'.format(family_name, members))

输出:

代码语言:javascript
复制
family name: Simpson, members: [u'Hommer', u'Marge', u'Bart']
family name: Griffin, members: [u'Peter', u'Brian', u'Meg']
票数 16
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12792998

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档