Home > Back-end >  XMLStart insert a line in XML file
XMLStart insert a line in XML file

Time:10-14

This is how my XML looks like.

<?xml version='1.0' encoding='utf-8'?>
<manifest android:hardwareAccelerated="true" android:versionCode="xxxxxxxx" android:versionName="xxxxx" package="xxxxxx" xmlns:android="xxxxxxxxxxxxxx">
    <application android:hardwareAccelerated="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true">
    </application>
    <uses-feature android:name="android.hardware.camera.front" android:required="false" />
</manifest>

I need to add the below line after the <application

android:networkSecurityConfig="@xml/network_security_config" android:requestLegacyExternalStorage="true"

So, the output should look like

<?xml version='1.0' encoding='utf-8'?>
<manifest android:hardwareAccelerated="true" android:versionCode="xxxxxxxx" android:versionName="xxxxx" package="xxxxxx" xmlns:android="xxxxxxxxxxxxxx">
    <application android:networkSecurityConfig="@xml/network_security_config" android:requestLegacyExternalStorage="true" android:hardwareAccelerated="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true">
    </application>
    <uses-feature android:name="android.hardware.camera.front" android:required="false" />
</manifest>

I've tried sed command but still no luck. everybody suggests to use XMLSTART.

sed -i '/<application/a android:networkSecurityConfig="@xml/network_security_config" android:requestLegacyExternalStorage="true"' AndroidManifest.xml

CodePudding user response:

If xmlstarlet is not available or not preferred, adding an attribute to an element can be done with xmllint with a bit of work

# get uses-feature element
uf="$(xmllint --xpath '/manifest/uses-feature' tmp.xml)"

# get application attributes
attrs="$(xmllint --xpath '/manifest/application/@*' tmp.xml | tr '\n' ' ')"

# append desired attributes
attrs =' android:networkSecurityConfig="@xml/network_security_config" android:requestLegacyExternalStorage="true"'

# build manifest inner xml
inner="<application $attrs></application>$uf"
# restore manifest inner xml (with @CharlesDuffy kind suggestion)
printf '%s\n' setrootns 'cd /manifest' "set $inner" save bye  | xmllint --shell tmp.xml

Note: output from xmllint --xpath '/manifest/application/@*' tmp.xml contains new lines that must be removed before using it on set command

android:hardwareAccelerated="true"
 android:icon="@mipmap/ic_launcher"
 android:label="@string/app_name"
 android:supportsRtl="true"

For other cases where content contains several nodes

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="xxxxxxxxxxxxxx" android:hardwareAccelerated="true" android:versionCode="xxxxxxxx" android:versionName="xxxxx" package="xxxxxx">
  <a>text1</a>

  <application android:hardwareAccelerated="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true"/>
  <uses-feature android:name="android.hardware.camera.front" android:required="false"/>
  
  <b>
      <c>text2</c>
  </b>
</manifest>

the following XPath should be used to get everything but the element to be changed

xmllint --xpath '/manifest/*[not(name()="application")]' tmp.xml

Result

<a>text1</a>
<uses-feature android:name="android.hardware.camera.front" android:required="false"/>
<b>
      <c>text2</c>
  </b>

CodePudding user response:

This might look like:

xmlstarlet ed \
  -i '/manifest/application' -t attr -n android:networkSecurityConfig -v '@xml/network_security_config' \
  -i '/manifest/application' -t attr -n android:requestLegacyExternalStorage -v true \
  <in.xml >out.xml
  • Related