xml = """<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.wearable.timer" >
<uses-sdk android:minSdkVersion="20"
android:targetSdkVersion="22" />
<application
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@android:style/Theme.DeviceDefault.Light"
android:allowBackup="true">
</application>
</manifest>"""
To set the values, find the node then access it's attrib dict then set the new value on it's attribute by using QName where the first arg is the namespace URI and the second is the attribute name:
import lxml.etree as et
tree = et.fromstring(xml)
# holds namespace mappings
nsmap = tree.nsmap
# get prefix URI
android = tree.nsmap["android"]
# find app and set the attribute value.
tree.find("application", nsmap).attrib[et.QName(android, "allowBackup")] = "false"
tree.find("uses-sdk", nsmap).attrib[et.QName(android, "minSdkVersion")] = "17"
print(et.tostring(tree, pretty_print=True))
Which gives you:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.android.wearable.timer">
<uses-sdk android:minSdkVersion="17" android:targetSdkVersion="22"/>
<application android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@android:style/Theme.DeviceDefault.Light" android:allowBackup="false">
</application>
</manifest>
To read and write from and to a file, the logic is the same just at the end you write passing in the filename and any other args:
import lxml.etree as et
from StringIO import StringIO
tree = et.parse(StringIO(xml))
root = tree.getroot()
nsmap = root.nsmap
android = nsmap["android"]
tree.find("application", nsmap).attrib[et.QName(android, "allowBackup")] = "false"
tree.find("uses-sdk", nsmap).attrib[et.QName(android, "minSdkVersion")] = "17"
# write the updated html to "new.xml"
tree.write("new.xml", encoding="utf-8")
new.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.android.wearable.timer">
<uses-sdk android:minSdkVersion="17" android:targetSdkVersion="22"/>
<application android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@android:style/Theme.DeviceDefault.Light" android:allowBackup="false">
</application>
</manifest>
You now know how to write the changes, as for missing attributes it works as is, if the value exists we update it, if not we create it:
# no minSDk...
In [31]: !cat test.xml<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.wearable.timer" >
<uses-sdk android:targetSdkVersion="22" />
<application
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@android:style/Theme.DeviceDefault.Light"
android:allowBackup="true">
</application>
</manifest>
In [32]: tree = et.parse("test.xml")
In [33]: root = tree.getroot()
In [34]: nsmap = root.nsmap
In [35]: android = nsmap["android"]
In [36]: tree.find("uses-sdk", nsmap).attrib[et.QName(android, "minSdkVersion")] = "17"
In [37]: tree.write("test.xml", encoding="utf-8")
# New attribute and value created.
In [38]: !cat test.xml<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.android.wearable.timer">
<uses-sdk android:targetSdkVersion="22" android:minSdkVersion="17"/>
<application android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@android:style/Theme.DeviceDefault.Light" android:allowBackup="true">
</application>
</manifest>
In [39]: