prosseek
prosseek

Reputation: 190769

Adding sibling element in ElementTree with Python

With XML such as

<a>
  <b>
  </b>
</a>

I need to add a sibling of something like

<a>
  <b>
  </b>
  <b'>
  </b'>
</a>

Does ElementTree has a function to add a sibling node? If not, I guess I need a function to get a parent node and add a child node, how can I do that?

Upvotes: 4

Views: 3194

Answers (3)

Steven
Steven

Reputation: 28666

In the standard lib's version, you cannot directly access the parent, you'll have to work down from the parent, or keep track of parent-child relations yourself, read these tips (from the author of the library).

If you use lxml however, there is the getparent() method (you have getnext() and getprevious() as well), but even more convenient: there is addnext() and addprevious().

So, choose one of these solutions, based on what ElementTree implementation you are using (or maybe even switch your implementation)

Upvotes: 7

eyquem
eyquem

Reputation: 27575

With what is at hand:

import re

def sibling(bal,text):
    print 'bal ==' + bal + '\n' # + '\n\n' + s

    def aux(match):
        # match.group(4) is '/' or None    
        return ("%s%s<%s'/>%s" % match.group(1,2,3,6) if match.group(4)
                else "%s%s<%s'>%s'>%s" % match.group(1,2,3,5,6))

    return re.sub('('
                  '(^\s*)<(' + bal + ')(?: [^/>]+)?'  # 2 and 3
                  '(?:(/)|>(?:.*?)((?:(?:\n|\r\n?)\\2)?</\\3))' # 4 and 5
                  '>(\n|\r\n?|\Z)' # 6
                  ')',
                  aux, text, flags = re.MULTILINE|re.DOTALL)


ch = """\
<a>
  <b>
  </b>
</a>
"""

dh = """\
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:dd="http://example.com/ns/1.0" xml:lang="en-US">
<entry>
    <dd:country_code>USA</dd:country_code>
    <content type="html">Hello World!</content>
    <OTF>
      <FECS state="disabled" version="2.2.0.0">
        <BackEndCompatibility major="2.2" state="disabled">
            <BackEnd state="disabled" version="2.2.0.0"/>
            <Forth type="ziwi">d,;%er*dkj@jkber-uyr</Forth>
        </BackEndCompatibility>
      </FECS>
    </OTF>
</entry>
"""

print sibling('a',ch)
print '------------------------------------------------------'
print sibling('b',ch)
print '------------------------------------------------------'

for x in ('entry','dd:country_code','content','OTF','FECS',
          'BackEndCompatibility','BackEnd','Forth'):
    print sibling(x,dh)
    print '------------------------------------------------------'

Result:

bal ==a

<a>
  <b>
  </b>
</a>
<a'>
</a'>

------------------------------------------------------
bal ==b

<a>
  <b>
  </b>
  <b'>
  </b'>
</a>

------------------------------------------------------
bal ==entry

<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:dd="http://example.com/ns/1.0" xml:lang="en-US">
<entry>
    <dd:country_code>USA</dd:country_code>
    <content type="html">Hello World!</content>
    <OTF>
      <FECS state="disabled" version="2.2.0.0">
        <BackEndCompatibility major="2.2" state="disabled">
            <BackEnd state="disabled" version="2.2.0.0"/>
            <Forth type="ziwi">d,;%er*dkj@jkber-uyr</Forth>
        </BackEndCompatibility>
      </FECS>
    </OTF>
</entry>
<entry'>
</entry'>

------------------------------------------------------
bal ==dd:country_code

<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:dd="http://example.com/ns/1.0" xml:lang="en-US">
<entry>
    <dd:country_code>USA</dd:country_code>
    <dd:country_code'></dd:country_code'>
    <content type="html">Hello World!</content>
    <OTF>
      <FECS state="disabled" version="2.2.0.0">
        <BackEndCompatibility major="2.2" state="disabled">
            <BackEnd state="disabled" version="2.2.0.0"/>
            <Forth type="ziwi">d,;%er*dkj@jkber-uyr</Forth>
        </BackEndCompatibility>
      </FECS>
    </OTF>
</entry>

------------------------------------------------------
bal ==content

<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:dd="http://example.com/ns/1.0" xml:lang="en-US">
<entry>
    <dd:country_code>USA</dd:country_code>
    <content type="html">Hello World!</content>
    <content'></content'>
    <OTF>
      <FECS state="disabled" version="2.2.0.0">
        <BackEndCompatibility major="2.2" state="disabled">
            <BackEnd state="disabled" version="2.2.0.0"/>
            <Forth type="ziwi">d,;%er*dkj@jkber-uyr</Forth>
        </BackEndCompatibility>
      </FECS>
    </OTF>
</entry>

------------------------------------------------------
bal ==OTF

<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:dd="http://example.com/ns/1.0" xml:lang="en-US">
<entry>
    <dd:country_code>USA</dd:country_code>
    <content type="html">Hello World!</content>
    <OTF>
      <FECS state="disabled" version="2.2.0.0">
        <BackEndCompatibility major="2.2" state="disabled">
            <BackEnd state="disabled" version="2.2.0.0"/>
            <Forth type="ziwi">d,;%er*dkj@jkber-uyr</Forth>
        </BackEndCompatibility>
      </FECS>
    </OTF>
    <OTF'>
    </OTF'>
</entry>

------------------------------------------------------
bal ==FECS

<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:dd="http://example.com/ns/1.0" xml:lang="en-US">
<entry>
    <dd:country_code>USA</dd:country_code>
    <content type="html">Hello World!</content>
    <OTF>
      <FECS state="disabled" version="2.2.0.0">
        <BackEndCompatibility major="2.2" state="disabled">
            <BackEnd state="disabled" version="2.2.0.0"/>
            <Forth type="ziwi">d,;%er*dkj@jkber-uyr</Forth>
        </BackEndCompatibility>
      </FECS>
      <FECS'>
      </FECS'>
    </OTF>
</entry>

------------------------------------------------------
bal ==BackEndCompatibility

<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:dd="http://example.com/ns/1.0" xml:lang="en-US">
<entry>
    <dd:country_code>USA</dd:country_code>
    <content type="html">Hello World!</content>
    <OTF>
      <FECS state="disabled" version="2.2.0.0">
        <BackEndCompatibility major="2.2" state="disabled">
            <BackEnd state="disabled" version="2.2.0.0"/>
            <Forth type="ziwi">d,;%er*dkj@jkber-uyr</Forth>
        </BackEndCompatibility>
        <BackEndCompatibility'>
        </BackEndCompatibility'>
      </FECS>
    </OTF>
</entry>

------------------------------------------------------
bal ==BackEnd

<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:dd="http://example.com/ns/1.0" xml:lang="en-US">
<entry>
    <dd:country_code>USA</dd:country_code>
    <content type="html">Hello World!</content>
    <OTF>
      <FECS state="disabled" version="2.2.0.0">
        <BackEndCompatibility major="2.2" state="disabled">
            <BackEnd state="disabled" version="2.2.0.0"/>
            <BackEnd'/>
            <Forth type="ziwi">d,;%er*dkj@jkber-uyr</Forth>
        </BackEndCompatibility>
      </FECS>
    </OTF>
</entry>

------------------------------------------------------
bal ==Forth

<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:dd="http://example.com/ns/1.0" xml:lang="en-US">
<entry>
    <dd:country_code>USA</dd:country_code>
    <content type="html">Hello World!</content>
    <OTF>
      <FECS state="disabled" version="2.2.0.0">
        <BackEndCompatibility major="2.2" state="disabled">
            <BackEnd state="disabled" version="2.2.0.0"/>
            <Forth type="ziwi">d,;%er*dkj@jkber-uyr</Forth>
            <Forth'></Forth'>
        </BackEndCompatibility>
      </FECS>
    </OTF>
</entry>

------------------------------------------------------

It works for 'a' and

"""\
<a>
  <b>
  </b>
</a>
"""

but not

"""\
<a>
  <b>
  </b>
</a>"""

Upvotes: -4

Wogan
Wogan

Reputation: 72707

The default ElementTree implementation included in the Python Standard Library does not have a method to get a parent node.

However, if you can use lxml's etree implementation then there is a getparent() method.

Upvotes: 1

Related Questions