简体   繁体   中英

lxml, add SubElement to SubElement

I've created an XML that looks like this.

<?xml version='1.0' encoding='utf-8' standalone='no'?>
<flow xlmns="urn:opendaylight:flow:inventory">
  <strict>false</strict>
  <instructions>
    <instruction>
      <apply-action>
        <action>
          <order>0</order>
          <dec-nw-ttl/>
        </action>
      </apply-action>
    </instruction>
  </instructions>

I'm sending it to a function that takes two parameters, flow (the XML), and actions (a list of new actions I want to add):

def add_flow_action(flow, actions):
   for newaction in actions:
      etree.SubElement(action, newaction)
   return flow

The function is meant to add more SubElements under the parent named action, so that it looks like this:

<?xml version='1.0' encoding='utf-8' standalone='no'?>
<flow xlmns="urn:opendaylight:flow:inventory">
  <strict>false</strict>
  <instructions>
    <instruction>
      <apply-action>
        <action>
          <order>0</order>
          <dec-nw-ttl/>
          <new-action-1/>      #Comment: NEW ACTION
          <new-action-2/>      #Comment: NEW ACTION
        </action>
      </apply-action>
    </instruction>
  </instructions>

This doesn't work, and it throws the error: TypeError: Argument '_parent' has incorrect type (expected lxml.etree._Element, got list)

Any ideas how to change the function to do this?

You should first find an action element and only then create SubElement s in it:

from lxml import etree

data = """<?xml version='1.0' encoding='utf-8' standalone='no'?>
<flow xlmns="urn:opendaylight:flow:inventory">
  <strict>false</strict>
  <instructions>
    <instruction>
      <apply-action>
        <action>
          <order>0</order>
          <dec-nw-ttl/>
        </action>
      </apply-action>
    </instruction>
  </instructions>
</flow>
"""


def add_flow_action(flow, actions):
    action = flow.xpath('//action')[0]
    for newaction in actions:
        etree.SubElement(action, newaction)
    return flow

tree = etree.fromstring(data)
result = add_flow_action(tree, ['new-action-1', 'new-action-2'])

print etree.tostring(result)

prints:

<flow xlmns="urn:opendaylight:flow:inventory">
  <strict>false</strict>
  <instructions>
    <instruction>
      <apply-action>
        <action>
          <order>0</order>
          <dec-nw-ttl/>
          <new-action-1/>
          <new-action-2/>
        </action>
      </apply-action>
    </instruction>
  </instructions>
</flow>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM