1

I got an XML file :

<?xml version="1.0"?>
<WLANProfile xmlns="http://www.microsoft.com/networking/WLAN/profile/v1">
    <name>antigon</name>
    <SSIDConfig>
        <SSID>
            <name>antigon</name>
        </SSID>
    </SSIDConfig>
    <connectionType>ESS</connectionType>
    <connectionMode>auto</connectionMode>
    <MSM>
        <security>
            <authEncryption>
                <authentication>WPA2PSK</authentication>
                <encryption>AES</encryption>
                <useOneX>false</useOneX>
            </authEncryption>
            <sharedKey>
                <keyType>passPhrase</keyType>
                <protected>false</protected>
                <keyMaterial>THIS IS WHAT I WANNA GET</keyMaterial>
            </sharedKey>
        </security>
    </MSM>
    <MacRandomization xmlns="http://www.microsoft.com/networking/WLAN/profile/v3">
        <enableRandomization>false</enableRandomization>
    </MacRandomization>
</WLANProfile>

I know the logic of HTML/XML, but I can't find how to get the thing "THIS IS WHAT I WANNA GET", with Etree and python, both in last version. Could someone help me ? Thanks a lot !

Daniel Haley
  • 51,389
  • 6
  • 69
  • 95
Quantum Sushi
  • 504
  • 7
  • 23
  • Is this `etree` part of the built-in `xml` library or the pip-installed `lxml` library? – C.Nivs Apr 08 '20 at 19:07
  • 1
    You're most likely having an issue because of the default namespace. Take a look at the accepted answer to this question: https://stackoverflow.com/questions/40796231/how-does-xpath-deal-with-xml-namespaces It has examples of ElementTree and lxml. If you still have problems, please update your answer with some code so we can reproduce your issue. – Daniel Haley Apr 08 '20 at 21:17
  • 2
    Did you try reading the examples of xpath in the Python documentation for ElementTree? See https://docs.python.org/3/library/xml.etree.elementtree.html#xpath-support – DisappointedByUnaccountableMod Apr 08 '20 at 22:07
  • 2
    And yes edit your code into your question. StackOverflow is not a code writing service. – DisappointedByUnaccountableMod Apr 08 '20 at 22:07
  • Thanks to everyone ! Yeah, it's Element Tree from lxml, and I've read the documentation about it. But all I can get with what I produce is for exemple : ```What I wanna get but don't get``` So I'm gonna have a look to these namespaces... I'll keep this updated ! – Quantum Sushi Apr 09 '20 at 08:17

2 Answers2

0

Below

import xml.etree.ElementTree as ET
import re

xml = '''<?xml version="1.0"?>
<WLANProfile xmlns="http://www.microsoft.com/networking/WLAN/profile/v1">
    <name>antigon</name>
    <SSIDConfig>
        <SSID>
            <name>antigon</name>
        </SSID>
    </SSIDConfig>
    <connectionType>ESS</connectionType>
    <connectionMode>auto</connectionMode>
    <MSM>
        <security>
            <authEncryption>
                <authentication>WPA2PSK</authentication>
                <encryption>AES</encryption>
                <useOneX>false</useOneX>
            </authEncryption>
            <sharedKey>
                <keyType>passPhrase</keyType>
                <protected>false</protected>
                <keyMaterial>THIS IS WHAT I WANNA GET</keyMaterial>
            </sharedKey>
        </security>
    </MSM>
    <MacRandomization xmlns="http://www.microsoft.com/networking/WLAN/profile/v3">
        <enableRandomization>false</enableRandomization>
    </MacRandomization>
</WLANProfile>'''
xml = re.sub(' xmlns="[^"]+"', '', xml, count=1)
root = ET.fromstring(xml)
key_material = root.find('.//keyMaterial')
print(key_material.text)

output

THIS IS WHAT I WANNA GET
balderman
  • 22,927
  • 7
  • 34
  • 52
  • WOW, thanks, this is exactly what I wanna get... Or almost. Because here you're parsing a string... And I want to parse from the document, and be able to write and modify the "THIS IS WHAT I WANNA GET". But maybe, if I take this code and modify it a bit, I'll be able to do this... The thing I don't understand is that line : xml = re.sub(' xmlns="[^"]+"', '', xml, count=1). What does that mean ? – Quantum Sushi Apr 09 '20 at 08:51
  • see https://stackoverflow.com/questions/13412496/python-elementtree-module-how-to-ignore-the-namespace-of-xml-files-to-locate-ma – balderman Apr 09 '20 at 08:52
  • Load the file into a string. call the string variable `xml` , call `xml = re.sub(' xmlns="[^"]+"', '', xml, count=1)` and you are done. – balderman Apr 09 '20 at 08:57
  • Yeah, but doesn't this make writing into the file more complicated ? And what is that re.sub thing ? – Quantum Sushi Apr 09 '20 at 14:35
  • Yeah I can hear that but what I say is if I use the file as a string will I be able to modify it etc ? Because to modify a specific node I will have the same problem : find it. So isn't it better to just find one way ? – Quantum Sushi Apr 09 '20 at 16:47
  • @TheMachinist - What you're modifying is the tree. Whether the tree is created from parsing a string or a file doesn't really matter. You'll still have to serialize/write the tree back to a file. Also, imo, it's better to learn how to properly handle namespaces instead of stripping them with a regex hack. – Daniel Haley Apr 09 '20 at 16:55
  • Ok @Daniel Haley, I'm kinda knew with xml parsing in python, so "regex hack" and "namespaces" and so aren't really clear. I'm gonna have a look at this, but my original problem is that into the documentation I can't find a way to do what I told above... So I was asking if anybody had an idea of an easy way to do it, and after, modifying the tree won't be difficult with the documentation. Why I don't wanna use a string is because after, I'll need to use this .xml for another thing... It's a wifi profile, I need to change the key, and then export it with a batch... Well it's ok I'll see ! – Quantum Sushi Apr 09 '20 at 17:02
  • @TheMachinist - I'll add an answer that shows finding that element without stripping the default namespace with regex. – Daniel Haley Apr 09 '20 at 17:03
  • @DanielHaley Yeah... Yeah ok let's see this, thanks for your help :D – Quantum Sushi Apr 09 '20 at 17:04
0

See the docs (and this answer) for details on handling namespaces with ElementTree.

Here's an example:

import xml.etree.ElementTree as ET

ns_map = {"wlan": "http://www.microsoft.com/networking/WLAN/profile/v1"}

tree = ET.parse("input.xml")

print(tree.find(".//wlan:keyMaterial", namespaces=ns_map).text)

prints...

THIS IS WHAT I WANNA GET

If you want to modify that value and save it to a file, try something like this:

import xml.etree.ElementTree as ET

ns_map = {"wlan": "http://www.microsoft.com/networking/WLAN/profile/v1"}

# Need this to make sure a prefix isn't added to your namespace declaration.
ET.register_namespace("", ns_map.get("wlan"))

tree = ET.parse("input.xml")

try:
    tree.find(".//wlan:keyMaterial", namespaces=ns_map).text = "NEW VALUE!"
except AttributeError:
    print("Unable to modify the keyMaterial value.")

tree.write("output.xml", xml_declaration=True, encoding="utf-8")

Output (output.xml)

<?xml version='1.0' encoding='utf-8'?>
<WLANProfile xmlns="http://www.microsoft.com/networking/WLAN/profile/v1" xmlns:ns1="http://www.microsoft.com/networking/WLAN/profile/v3">
    <name>antigon</name>
    <SSIDConfig>
        <SSID>
            <name>antigon</name>
        </SSID>
    </SSIDConfig>
    <connectionType>ESS</connectionType>
    <connectionMode>auto</connectionMode>
    <MSM>
        <security>
            <authEncryption>
                <authentication>WPA2PSK</authentication>
                <encryption>AES</encryption>
                <useOneX>false</useOneX>
            </authEncryption>
            <sharedKey>
                <keyType>passPhrase</keyType>
                <protected>false</protected>
                <keyMaterial>NEW VALUE!</keyMaterial>
            </sharedKey>
        </security>
    </MSM>
    <ns1:MacRandomization>
        <ns1:enableRandomization>false</ns1:enableRandomization>
    </ns1:MacRandomization>
</WLANProfile>

Note: ElementTree doesn't do a great job handling more than one default namespace, so that's why the "ns1" prefix is added to the output.

Daniel Haley
  • 51,389
  • 6
  • 69
  • 95
  • Thank you so much ! This is exactly what I was searching for, the thing is closed now ! ^^ Gonna try this immediately... Thanks ! – Quantum Sushi Apr 09 '20 at 17:26