从XML文件创建字典

时间:2014-10-30 21:07:49

标签: python xml dictionary

我有和XML文件看起来像这样:

<?xml version="1.0" encoding ="utf8"?>
<rebase>
  <Organism>
    <Name>Aminomonas paucivorans</Name>
      <Enzyme>M1.Apa12260I</Enzyme>
        <Motif>GGAGNNNNNGGC</Motif>
      <Enzyme>M2.Apa12260I</Enzyme>
        <Motif>GGAGNNNNNGGC</Motif>
  </Organism>
  <Organism>
    <Name>Bacillus cellulosilyticus</Name>
      <Enzyme>M1.BceNI</Enzyme>
        <Motif>CCCNNNNNCTC</Motif>
      <Enzyme>M2.BceNI</Enzyme>
        <Motif>CCCNNNNNCTC</Motif>
  </Organism>

对于每个Organism,有多个EnzymesMotifs。酶是独特的,但图案可以重复。所以我尝试创建一个字典,以酶为关键,主题为值。这是我的代码:

    import xml.etree.ElementTree as ET

    def lister():
        tree = ET.parse('rebase.xml')
        rebase = tree.getroot()

        data_dict = {}

        for each_organism in rebase.findall('Organism'):
            try:
                enzyme = each_organism.find('Enzyme').text
            except AttributeError:
                continue

            for motif in each_organism.findall('Motif'):
                motif = motif.text
                data_dict[enzyme] = motif
        return data_dict

然而,字典似乎省略了不少条目。我似乎能理解这个问题是什么。任何帮助将不胜感激。

修改

用户发布了一个解决方案,但随后将其删除,但我可以及时复制它:

for each_organism in rebase.findall('Organism'):
        try:
            enzyme = each_organism.find('Enzyme').text
        except AttributeError:
            continue
        data_dict[enzyme] = []
        for motif in each_organism.findall('Motif'):
            data_dict[enzyme].append(motif.text)
    return data_dict

然而,在这种情况下返回的词典是错误的,并且为什么:

酶 - 基序对是独一无二的。这样1种酶只有1个基序。在我的文件中,酶只出现一次,一个基序可以多次出现,但它属于不同的酶,因此该对是独特的。 EDIT 下的代码是这样的:

假设和酶 - 具有基序M.APaI的{​​{1}}和具有基序GATC的另一个M.APaII。两种酶都非常相似(仅在最后一个字符TCAG中有所不同)。该代码将两个基序绑定到创建I

的第一个酶

1 个答案:

答案 0 :(得分:1)

我看到的第一个大问题是你只是在任何给定的生物体内寻找第一个酶。如果你想找到每种酶的发生率,你应该使用:

 for enzyme in each_organism.findall('Enzyme'):
     # add to dictionary here

第二个问题是您的XML格式与您似乎使用字典构建的数据关系不匹配。在XML,Enzyme,Motif和Name中都是有机体的孩子,但是你将主题指定为与酶键相关的值。在迭代事件的发生率以及哪一个应该与另一个事件相关联时,你无法知道,因为它们在对象中没有任何逻辑分离而全部被卡在一起。

我可能会误解你的目的,但似乎你可以通过构建有机体和酶类对象来更好地服务,而不是强迫两个(显然)不相关的概念成为一个键值关系。

这可能是这样,并封装你的字段:

class Organism:
    # where enzymes is an iterable of Enzyme
    def __init__(self, name, enzymes):
        self.name = name
        self.enzymes = enzymes

和你的酶对象:

class Enzyme:
    # where motifs is an iterable of string
    def __init__(self, motifs):
        self.motifs = motifs

所有这些仍然需要对XML文件进行某种更改。除非你只是按行解析(这显然不是XML的要点),否则我无法想出任何简单的方法,你现在能够找出哪些Motif属于哪种酶。

编辑:看到你正在询问如何通过每个酶节点盲目地迭代,并假设你总是有一个Name元素,你有每个酶的一个Motif,以及Name之后的每个元素是Enzymes然后是Motif(例如EMEM等)你应该能够做到这一点:

i = 0
enzymes = []
motifs = []

for element in each_organism:
    # skip the first Name child
    if i == 0:
        continue
    # if we're at an odd index, indicating an enzyme
    if i % 2 == 1:
        enzymes.append(element.text)
    # if we're at an even index, indicating the related motif
    elif i % 2 == 0:
        motifs.append(element.text)

    i += 1

然后,假设我布置的每个假设,可能还有几个(我甚至不是100%确定etree总是自上而下迭代元素),保持为真,任何主题都在基序中的任何给定指数都属于酶中相同指数的酶。如果我还没有说清楚:这是非常脆弱的代码。