5

我有一个xml格式的文件:

<NewDataSet>
    <Root>
        <Phonemic>and</Phonemic>
        <Phonetic>nd</Phonetic>
        <Description/>
        <Start>0</Start>
        <End>8262</End>
    </Root>
    <Root>
        <Phonemic>comfortable</Phonemic>
        <Phonetic>comfetebl</Phonetic>
        <Description>adj</Description>
        <Start>61404</Start>
        <End>72624</End>
    </Root>
</NewDataSet>

我需要对其进行处理,例如,当用户输入 时nd,程序将其与<Phonetic>标签匹配并and<Phonemic>部件返回。我想也许如果我可以将 xml 文件转换为字典,我将能够遍历数据并在需要时查找信息。

我搜索并找到了用于相同目的的xmltodict :

import xmltodict
with open(r'path\to\1.xml', encoding='utf-8', errors='ignore') as fd:
    obj = xmltodict.parse(fd.read())

运行它给了我一个ordered dict

>>> obj
OrderedDict([('NewDataSet', OrderedDict([('Root', [OrderedDict([('Phonemic', 'and'), ('Phonetic', 'nd'), ('Description', None), ('Start', '0'), ('End', '8262')]), OrderedDict([('Phonemic', 'comfortable'), ('Phonetic', 'comfetebl'), ('Description', 'adj'), ('Start', '61404'), ('End', '72624')])])]))])

现在不幸的是,这并没有让事情变得更简单,我不确定如何使用新的数据结构来实现程序。例如要访问nd我必须写:

obj['NewDataSet']['Root'][0]['Phonetic']

这非常复杂。我试图把它变成一个普通的字典,dict()但是因为它是嵌套的,所以内层保持有序,我的数据很大。

4

3 回答 3

6

如果您以obj['NewDataSet']['Root'][0]['Phonetic']IMO 身份访问此内容,则说明您做得不对。

相反,您可以执行以下操作

obj = obj["NewDataSet"]
root_elements = obj["Root"] if type(obj) == OrderedDict else [obj["Root"]] 
# Above step ensures that root_elements is always a list
for element in root_elements:
    print element["Phonetic"]

尽管这段代码看起来要长得多,但优点是一旦开始处理足够大的 xml,它将更加紧凑和模块化。

PS:我遇到了同样的问题xmltodict。但不是使用xml.etree.ElementTree来解析 xml 文件,xmltodict 更容易使用,因为代码库更小,而且我不必处理 xml 模块的其他空洞。

编辑

以下代码对我有用

import xmltodict
from collections import OrderedDict

xmldata = """<NewDataSet>
    <Root>
        <Phonemic>and</Phonemic>
        <Phonetic>nd</Phonetic>
        <Description/>
        <Start>0</Start>
        <End>8262</End>
    </Root>
    <Root>
        <Phonemic>comfortable</Phonemic>
        <Phonetic>comfetebl</Phonetic>
        <Description>adj</Description>
        <Start>61404</Start>
        <End>72624</End>
    </Root>
</NewDataSet>"""

obj = xmltodict.parse(xmldata)
obj = obj["NewDataSet"]
root_elements = obj["Root"] if type(obj) == OrderedDict else [obj["Root"]] 
# Above step ensures that root_elements is always a list
for element in root_elements:
    print element["Phonetic"]
于 2014-11-14T09:16:04.080 回答
5

您实际上可以通过设置额外的关键字参数来避免转换为 OrderedDict:

obj = xmltodict.parse(xmldata, dict_constructor=dict)

parse将关键字参数转发到_DictSAXHandler并且dict_constructor默认设置为OrderedDict.

于 2018-06-18T14:38:48.277 回答
0

穆的回答对我有用,我唯一需要改变的是棘手的确保 root_element 始终是一个列表步骤。:-

import xmltodict
from collections import OrderedDict

xmldata = """<NewDataSet>
    <Root>
        <Phonemic>and</Phonemic>
        <Phonetic>nd</Phonetic>
        <Description/>
        <Start>0</Start>
        <End>8262</End>
    </Root>
    <Root>
        <Phonemic>comfortable</Phonemic>
        <Phonetic>comfetebl</Phonetic>
        <Description>adj</Description>
        <Start>61404</Start>
        <End>72624</End>
    </Root>
</NewDataSet>"""

obj = xmltodict.parse(xmldata)
obj = obj["NewDataSet"]
root_elements = obj["Root"] if type(obj["Root"]) == list else [obj["Root"]] 
# Above step ensures that root_elements is always a list
# Is obj["Root"] a list already, then use obj["Root"], otherwise make single element list.
for element in root_elements:
    print element["Phonetic"]
于 2016-12-03T14:14:09.110 回答