使用lxml加载子级会覆盖以前加载的元素

时间:2013-04-02 21:05:45

标签: python lxml

我在Python中编写了一些自定义类,有两个函数可以使用lxml将类加载并保存到xml文件中。保存功能和大多数加载功能都有效,但我在加载xml时遇到问题。当我读取<flows>并在<flow>标记和元素内时,在每次迭代时,先前的值都会被覆盖。例如,我有三个带有<step>元素的<flow>元素:1 <flow>第一个<step>,2 <flow>第二个<step>和3 { {1}}第三个<flow>。值似乎已成功加载,但最终每个值都会被以下<step>覆盖,因此我最终加载了3 <step>,每个{3} <step>

这是xml:

<flow>

这是python代码:

<step>
  <stepnumber>0</stepnumber>
  <steptitle>first step</steptitle>
  <participation>None</participation>
  <tools>tools</tools>
  <rules>rules</rules>
  <actors>
    <actor>first actor</actor>
    <actor>second actor</actor>
  </actors>
  <picture>none</picture>
  <flows>
   <flow>
     <number>0</number>
     <type>Information flow</type>
     <what>bits</what>
     <direction>From the first actor to the second one</direction>
     <firstactor>second actor</firstactor>
     <secondactor>first actor</secondactor>
   </flow>
  </flows>
</step>
<step>
 <stepnumber>1</stepnumber>
 <steptitle>second step</steptitle>
 <participation>None</participation>
 <tools>tools</tools>
 <rules>rules</rules>
 <actors>
   <actor>first actor</actor>
   <actor>second actor</actor>
   <actor>third actor</actor>
 </actors>
 <picture>none</picture>
 <flows>
   <flow>
     <number>0</number>
     <type>Financial flow</type>
     <what>none</what>
     <direction>From the first actor to the second one</direction>
     <firstactor>third actor</firstactor>
     <secondactor>first actor</secondactor>
   </flow>
   <flow>
     <number>1</number>
     <type>Information flow</type>
     <what>bits</what>
     <direction>From the first actor to the second one</direction>
     <firstactor>second actor</firstactor>
     <secondactor>first actor</secondactor>
   </flow>
 </flows>
</step>
<step>
 <stepnumber>2</stepnumber>
 <steptitle>third step</steptitle>
 <participation>None</participation>
 <tools>tools</tools>
 <rules>rules</rules>
 <actors>
   <actor>first actor</actor>
   <actor>second actor</actor>
 </actors>
 <picture>none</picture>
 <flows>
   <flow>
     <number>0</number>
     <type>Financial flow</type>
     <what>none</what>
     <direction>Both directions</direction>
     <firstactor>first actor</firstactor>
     <secondactor>second actor</secondactor>
   </flow>
   <flow>
     <number>1</number>
     <type>Information flow</type>
     <what>bits</what>
     <direction>From the first actor to the second one</direction>
     <firstactor>first actor</firstactor>
     <secondactor>second actor</secondactor>
   </flow>
   <flow>
     <number>2</number>
     <type>Information flow</type>
     <what>bits</what>
     <direction>Both directions</direction>
     <firstactor>first actor</firstactor>
     <secondactor>second actor</secondactor>
   </flow>
 </flows>

和结果(前三次重复的最后一次流程)是:

    steplist = doc.xpath("//project/step")
    for k,m in enumerate(steplist):
        stepelements = m.getchildren()
        for l in stepelements:
            if l.tag == "stepnumber":
                self.steps[k] = step()
                self.steps[k].stepnumber = l.text
            elif l.tag == "steptitle":
                self.steps[k].title = l.text
            elif l.tag == "participation":
                self.steps[k].participation = l.text
            elif l.tag == "tools":
                self.steps[k].tools = l.text
            elif l.tag == "rules":
                self.steps[k].rules = l.text
            elif l.tag == "actors":
                self.steps[k].actors = []
                for j,i in enumerate(l.getchildren()):
                    self.steps[k].actors.append(l.getchildren()[j].text)
            elif l.tag == "picture":
                self.steps[k].picture = l.text
            elif l.tag == "flows":
                for s,r in enumerate(l.getchildren()):
                    self.steps[k].flows[s] = flow()
                    self.steps[k].flows[s].number = r.getchildren()[0].text
                    self.steps[k].flows[s].type = r.getchildren()[1].text
                    self.steps[k].flows[s].what = r.getchildren()[2].text
                    self.steps[k].flows[s].direction = r.getchildren()[3].text
                    self.steps[k].flows[s].actor1 = r.getchildren()[4].text
                    self.steps[k].flows[s].actor2 = r.getchildren()[5].text

我该如何解决这个问题? 完整文件可在此处获得: https://github.com/OpenP2PDesignOrg/OpenMetaDesignApp/blob/load/classes.py https://github.com/OpenP2PDesignOrg/OpenMetaDesignApp/blob/load/test2.meta

1 个答案:

答案 0 :(得分:1)

您对step.__init__的声明搞砸了,因为flow参数的默认参数为flow成员的所有值分配了相同的dict实例和相同的flow实例。在定义加载时评估,而不是在每次执行函数时评估。

在Python中执行默认参数的更常用的方法是什么你想要传递的东西是可变的/ by-reference是默认值是None,然后在你要做的函数中有一些逻辑

if flows is None:
    self.flows = {0: flows()}
else:
    self.flows = flows

self.flows = flows if flows is not None else {0: flows()}

或类似的东西。