Python Forum
Adding a node into an xml tree
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Adding a node into an xml tree
#1
Hi

I'm wondering on the best wày to include a node into an xml tree, at the right location in a list of siblings.

xml.etree.ElementTree does not expose any methode to do that.

I understand that, using this module, one has to obtain the list of the siblings, S, then to include the node at the right location of S, then to remove the siblings from their parent node P and, at last, to include S as P's children.

Is there another straightforward way to obtain this result ?

Arbiel
using Ubuntu 18.04.4 LTS, Python 3.8
having substituted «https://www.lilo.org/fr/» to google, «https://protonmail.com/» to any other unsafe mail service and bépo to azerty (french keyboard layouts)
Reply
#2
To be honest i never use ElementTree or any module with xml/html or http in the standard library.
Before i did answer some post with ElementTree or xml.dom.minidom,no i have deiced that i would never do that again.
That's because Beautiful Soup, lxml alone or in a combination dos a much better job.
Reply
#3
Hi snippsat

Thank you for this information. I can only agree that xml.etree and xml.dom.minidom are not very easy to use.

After having installed bs4 following the installation instructions, with «sudo apt-get install python3-bs4» and then with
remi@remi-Vostro-3550:~$ pip install beautifulsoup4
Defaulting to user installation because normal site-packages is not writeable
Requirement already satisfied: beautifulsoup4 in /usr/lib/python3/dist-packages (4.6.0)
WARNING: You are using pip version 20.0.2; however, version 20.1 is available.
You should consider upgrading via the '/usr/bin/python3.8 -m pip install --upgrade pip' command.
remi@remi-Vostro-3550
I had to modify sys.path to import bs4
remi@remi-Vostro-3550:~$ python
Python 3.8.2 (default, Apr 26 2020, 23:13:12) 
[GCC 7.5.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import bs4
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'bs4'
>>> import sys
>>> sys.path
['', '/usr/local/lib/python38.zip', '/usr/local/lib/python3.8', '/usr/local/lib/python3.8/lib-dynload', '/home/remi/.local/lib/python3.8/site-packages', '/usr/local/lib/python3.8/site-packages']
>>> sys.path.append('/usr/lib/python3/dist-packages (4.6.0)')
>>> sys.path
['', '/usr/local/lib/python38.zip', '/usr/local/lib/python3.8', '/usr/local/lib/python3.8/lib-dynload', '/home/remi/.local/lib/python3.8/site-packages', '/usr/local/lib/python3.8/site-packages', '/usr/lib/python3/dist-packages (4.6.0)']
>>> import bs4
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'bs4'
>>> sys.path[6]
'/usr/lib/python3/dist-packages (4.6.0)'
>>> sys.path[6]='/usr/lib/python3/dist-packages'
>>> from bs4 import BeautifulSoup
>>>
So my question is :

How can I have at python's launch specific directories included into sys.path (for this /usr/lib… as well as the directory where I keep my own scripts) ?

Arbiel
using Ubuntu 18.04.4 LTS, Python 3.8
having substituted «https://www.lilo.org/fr/» to google, «https://protonmail.com/» to any other unsafe mail service and bépo to azerty (french keyboard layouts)
Reply
#4
Hello!
First, you have to locate the element you want to add a child to it.
Then you just doing it. I took the example XML from w3schools - https://www.w3schools.com/xml/simple.xml
The XML file:
<breakfast_menu>
<food>
<name>Belgian Waffles</name>
<price>$5.95</price>
<description>
Two of our famous Belgian Waffles with plenty of real maple syrup
</description>
<calories>650</calories>
</food>
<food>
<name>Strawberry Belgian Waffles</name>
<price>$7.95</price>
<description>
Light Belgian waffles covered with strawberries and whipped cream
</description>
<calories>900</calories>
</food>
<food>
<name>Berry-Berry Belgian Waffles</name>
<price>$8.95</price>
<description>
Light Belgian waffles covered with an assortment of fresh berries and whipped cream
</description>
<calories>900</calories>
</food>
<food>
<name>French Toast</name>
<price>$4.50</price>
<description>
Thick slices made from our homemade sourdough bread
</description>
<calories>600</calories>
</food>
<food>
<name>Homestyle Breakfast</name>
<price>$6.95</price>
<description>
Two eggs, bacon or sausage, toast, and our ever-popular hash browns
</description>
<calories>950</calories>
</food>
</breakfast_menu>
The Python code:
from xml.etree import ElementTree as et

tree = et.parse('simple.xml')
root = tree.getroot()

target = root.find('food/[name="Berry-Berry Belgian Waffles"]')

new = et.SubElement(target, 'compliment') # compliment is the name of the new tag
new.text = 'Get two and we will add an ice cream.' # the content of the tag

tree.write('xml_ex2.xml')
The resulting XML:
<breakfast_menu>
<food>
<name>Belgian Waffles</name>
<price>$5.95</price>
<description>
Two of our famous Belgian Waffles with plenty of real maple syrup
</description>
<calories>650</calories>
</food>
<food>
<name>Strawberry Belgian Waffles</name>
<price>$7.95</price>
<description>
Light Belgian waffles covered with strawberries and whipped cream
</description>
<calories>900</calories>
</food>
<food>
<name>Berry-Berry Belgian Waffles</name>
<price>$8.95</price>
<description>
Light Belgian waffles covered with an assortment of fresh berries and whipped cream
</description>
<calories>900</calories>
<compliment>Get two and we will add an ice cream.</compliment>
</food>
<food>
<name>French Toast</name>
<price>$4.50</price>
<description>
Thick slices made from our homemade sourdough bread
</description>
<calories>600</calories>
</food>
<food>
<name>Homestyle Breakfast</name>
<price>$6.95</price>
<description>
Two eggs, bacon or sausage, toast, and our ever-popular hash browns
</description>
<calories>950</calories>
</food>
</breakfast_menu>
"As they say in Mexico 'dosvidaniya'. That makes two vidaniyas."
https://freedns.afraid.org
Reply
#5
Hi wavic

I'm afraid, you did not have time to read snippsat's suggestion and my reply to it. BeautifulSoup seems much more convenient to use as xml.etree and xml.dom.minidom, which I tried, but not quite whole satisfaction.

Anyway,you missed my real concern. My question, maybe not quite clear, was not to add a subelement as the last child of its father, but at a specific location inside all fathers's children. For example, between price and description.

My new concern now, is the way to have «/usr/lib/python3/dist-packages» in sys.path at Python's launch, without to have to
sys.path.append('/usr/lib/python3/dist-packages')
or any other repository of my choice.

I suppose there is a file somewhere to update, and I really don't know which it is.

Arbiel
using Ubuntu 18.04.4 LTS, Python 3.8
having substituted «https://www.lilo.org/fr/» to google, «https://protonmail.com/» to any other unsafe mail service and bépo to azerty (french keyboard layouts)
Reply
#6
insert method inserts a new node in specific position.
from xml.etree import ElementTree as et

tree = et.parse('simple.xml')
root = tree.getroot()

target = root.find('food/[name="Berry-Berry Belgian Waffles"]')
target.insert(2, et.Element('compliment', text="Get two and we will add an ice cream."))

tree.write('xml_ex2.xml')
I agree that using BeautifulSoup or lxml is more easy and convenient. XML module have not full support of XPath for example. Which makes searching by attribute... a pain.
"As they say in Mexico 'dosvidaniya'. That makes two vidaniyas."
https://freedns.afraid.org
Reply
#7
Quote:My new concern now, is the way to have «/usr/lib/python3/dist-packages» in sys.path at Python's launch, without to have to
sys.path.append('/usr/lib/python3/dist-packages')
You shall never have to this,if so you have messes up installation.
I guess you have install Python 3.8 yourself?
I do recommend pyenv Simple Python Version Management.

So i see when you type python it start python 3.8.
When you try to install you see what happens because normal site-packages is not writeable
Then it tell that is satisfied in /usr/lib/python3/dist-packages this is default Python 3 installation and not 3.8.
remi@remi-Vostro-3550:~$ pip install beautifulsoup4
Defaulting to user installation because normal site-packages is not writeable
Requirement already satisfied: beautifulsoup4 in /usr/lib/python3/dist-packages (4.6.0)
Here some option to try
pip -V # Should point to Python 3.8,if not use pip3

python -m pip install beautifulsoup4

pip install --user beautifulsoup4

# Not recommend,but this is what many do unfortunately
sudo pip install beautifulsoup4
Now type python again and test if bs4 work in Python 3.8.
Reply
#8
Hi snippsat

You are right. As I am lazy, I defined an alias
remi@remi-Vostro-3550:~$ alias python
alias python='python3.8'
remi@remi-Vostro-3550:~$ 
I don't remember how I installed Python and BeautifulSoup. I made a new BeautifulSoup install following your instruction
remi@remi-Vostro-3550:~$ pip -V
pip 20.1 from /home/remi/.local/lib/python3.8/site-packages/pip (python 3.8)
remi@remi-Vostro-3550:~$ python -m pip install beautifulsoup4
Defaulting to user installation because normal site-packages is not writeable
Collecting beautifulsoup4
  Using cached beautifulsoup4-4.9.0-py3-none-any.whl (109 kB)
Collecting soupsieve>1.2
  Using cached soupsieve-2.0-py2.py3-none-any.whl (32 kB)
Installing collected packages: soupsieve, beautifulsoup4
Successfully installed beautifulsoup4-4.9.0 soupsieve-2.0
remi@remi-Vostro-3550:~$ pip install --user beautifulsoup4
Requirement already satisfied: beautifulsoup4 in ./.local/lib/python3.8/site-packages (4.9.0)
Requirement already satisfied: soupsieve>1.2 in ./.local/lib/python3.8/site-packages (from beautifulsoup4) (2.0)
remi@remi-Vostro-3550:~$
I've removed bs4 and beautifulsoup4-4.6.0.egg-info from /usr/lib/python3/dist-packages as they now have been installed in /home/remi/.local/lib/python3.8/site-packages.

So, I still have a question regarding my own scripts.

Do I have to store them in /home/remi/.local/lib/python3.8/site-packages or could I let them in a specific directory, and in that case, how can I have this directory be included in sys.path at Python's launch when typing «Python» on the command line ? (I know it is included in sys.path[0] when I type «Python <my_script> on the command line)

Arbiel
using Ubuntu 18.04.4 LTS, Python 3.8
having substituted «https://www.lilo.org/fr/» to google, «https://protonmail.com/» to any other unsafe mail service and bépo to azerty (french keyboard layouts)
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  How we prune Alphabeta Tree Node Using BST concept Anldra12 4 2,362 May-18-2021, 09:17 AM
Last Post: Anldra12
  Adding markers to Folium map only adding last element. tantony 0 2,095 Oct-16-2019, 03:28 PM
Last Post: tantony

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020