【问题标题】:parse xml files block by block and get the values inside each block逐块解析xml文件并获取每个块内的值
【发布时间】:2017-08-20 20:03:22
【问题描述】:

我有一个 10 GB 的 xml 文件,其中包含不同块的列表。这是我的文件的 sn-p:

<image>
    <ref>www.test.com</ref>
    <label/>
    <number>0</number>
    <ID>ID0</ID>
    <name>test1</name>
    <comment>
        <line number="0">This is a comment</line>
        <line number="1">This is also another comment</line>
    </comment>
    <creationDate>2017-02-13T15:46:16-04:00</creationDate>
</image>

<result>
    <ref>www.test1.com</ref>
    <label/>
    <number>001</number>
    <ID>RE1</ID>
    <name>test2</name>
    <comment>
        <line number="0">This is a comment2</line>
    </comment>
    <creationDate>2017-01-13T15:46:16-04:00</creationDate>
</result>

<image>
    <ref>www.test3.com</ref>
    <label/>
    <number>1</number>
    <ID>ID1</ID>
    <value>10030</value>
    <name>test3</name>
    <comment>
        <line number="0">This is a comment3</line>
    </comment>
    <creationDate>2017-04-13T15:46:16-04:00</creationDate>
</image>

所以我的目标是使用 celementtreeiterparse 以序列化模式解析我的文件,但想一次获取每个块。例如,我喜欢获取整个 image 块,然后解析该块内的值。 例如,我需要获取第一个图像块 (*&lt;image&gt;... &lt;/image&gt;*) 块,然后在其中打印 www.test.com、0、id0、test1 的值,这是一个注释和 2017-02-13T15: 46:16-04:00。

所以我使用了以下代码,但它似乎只能逐行读取 xml 文件,也无法打印每行或元素内的值:

for event, element in ET.iterparse(pathtofile):
   print element.tag , element.attrib

你能帮我解决这个问题吗?我对 xml 解析完全陌生。 我还想将每个解析的块转换为 python 中的字典。有可能吗?

【问题讨论】:

    标签: python xml parsing xml-parsing


    【解决方案1】:

    它不是“逐行”读取您的 XML 文件。它正在在每个元素的末尾返回一个end 事件。也就是说,如果您的输入文件如下所示:

    <data>
      <widgets location="earth">
        <widget name="gizmo"/>
        <widget name="gadget"/>
        <widget name="thingamajig"/>
      </widgets>
    </data>
    

    iterparse 的简单调用的返回值序列将是:

    end <Element widget at 0x7f31e3132488>
    end <Element widget at 0x7f31e3123f38>
    end <Element widget at 0x7f31e3123ef0>
    end <Element widgets at 0x7f31e31327a0>
    end <Element data at 0x7f31e31324d0>
    

    如果你愿意,你也可以在每个元素的开头receive start events,像这样:

    for event, element in etree.iterparse(fd, events=('start', 'end')):
        print event, element
    

    输出将是:

    start <Element data at 0x7fccf78cc518>
    start <Element widgets at 0x7fccf78cc7e8>
    start <Element widget at 0x7fccf78cc4d0>
    end <Element widget at 0x7fccf78cc4d0>
    start <Element widget at 0x7fccf78bdf80>
    end <Element widget at 0x7fccf78bdf80>
    start <Element widget at 0x7fccf78bdf38>
    end <Element widget at 0x7fccf78bdf38>
    end <Element widgets at 0x7fccf78cc7e8>
    end <Element data at 0x7fccf78cc518>
    

    如果我想为每个location 构建一个widgets 列表,那么我可能想通过初始化一个列表来响应start 事件,然后将每个新小部件附加到该列表直到我到达结束元素,如:

    from lxml import etree
    
    with open('data2.xml') as fd:
        widgets = {}
        loc = None
    
        for event, element in etree.iterparse(fd, events=('start', 'end')):
            if event == 'start' and element.tag == 'widgets':
                loc = element.get('location')
                widgets[loc] = []
            elif event == 'end' and element.tag == 'widget':
                widgets[loc].append(element.get('name'))
    
        print widgets
    

    其输出为:

    {'earth': ['gizmo', 'gadget', 'thingamajig']}
    

    我希望这能让您了解如何处理输入文件中的每个感兴趣的块。

    【讨论】:

      猜你喜欢
      • 2023-03-18
      • 1970-01-01
      • 2019-09-23
      • 2018-05-23
      • 2015-07-18
      • 2011-12-03
      • 2023-04-03
      • 2011-12-05
      • 2010-10-14
      相关资源
      最近更新 更多