简体   繁体   中英

Addin multiple sub-elements with same tag to en XML tree with Python/Elementtree

I am reading data from a python dictionary and trying to add more book elements in the below tree. Below is just an examplke, i need to copy an element with it's child(s) but replace the content, in this case i need to copy the book element but replace title and author.

  <store>
    <bookstore>
        <book>
            <title lang="en">IT book</title>
            <author>Some IT Guy</author>
        </book>
    </bookstore>
  </store>

I use this code:

root = et.parse('Template.xml').getroot()
bookstore = root.find('bookstore')
book = root.find('bookstore').find('book')

Then i run the loop through a dictionary and trying to add new book elements under the bookstore:

for bk in bks:
    book.find('title').text = bk
    bookstore.append(book)

The result is that book elements are added to the bookstore, however they all contain title from the last iteration of the loop. I know i am doing something wrong here, but i can't understand what. I tried:

book[0].append(book) and book[-1].append(book)

But it did not help.

You changing the same object.

You need to actual copy the object with copy.deepcopy

Example:

import xml.etree.ElementTree as et
import copy

root = et.parse('Template.xml').getroot()
bookstore = root.find('bookstore')
book = root.find('bookstore').find('book')

bks = ["book_title_1", "book_title_2", "book_title_3"]
for bk in bks:
   new_book = copy.deepcopy(book)
   new_book.find('title').text = bk
   bookstore.append(new_book)

print et.tostring(root)

I'm guessing instead of books.append(book) you mean bookstore.append(book) .

Basically here you have a structure:

- store
  - bookstore
    - book
      - book infos

with book = root.find('bookstore').find('book') you are actually getting a reference to the (only) one you already have, and in the loop you keep updating its title and re-appending it to the store (so basically you are only overwriting the title). What you must do is to create every time a new Element (or clone it as Chertkov Pavel suggested, but you must remember to overwrite all the fields, or you may end up inheriting the wrong author) and append it to the bookstore:

for bk in bks:
    new_book = et.Element('book')

    # create and append title
    new_title = et.Element('title', attib={'lang':'eng'})
    new_title.text = bk
    new_book.append(new_title)

    # add also author and any other info
    # ...

    # append to the bookstore
    bookstore.append(new_book)

print et.tostring(root)

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