I'm trying to use xmlstarlet on my Mac to get the attribute value of an element from its sub-element, here is an example
I have an xml file with a lot of elements like this, the attributes like android:configChanges vary from element to element:
<activity android:configChanges="ABC" android:screenOrientation="XXX">
<intent-filter>
<action android:name="XYZ"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
the thing is that the value of category android:name
is unique to this element which is android.intent.category.LAUNCHER
.
Is there a way using xmllint or xmlstarlet where i run the
xmlstarlet <magic code> <filename>
the <magic code>
should be able to tell the value of android:configChanges
and android:screenOrientation
when it is provided that /activity/intent-filter/category android:name = "android.intent.category.LAUNCHER"
thus, the deisred output should be
android:configChanges="ABC" android screenOrientation="XXX"
so far the only thing i know is how to get the value of other sub-elements from a specific sub-element using
xmlstarlet sel -t -c "/activity/intent-filter/category[@android:name=android.intent.category.LAUNCHER]/*" file.xml
which returns
<action android:name="XYZ"/>
<category android:name="android.intent.category.LAUNCHER"/>
Any help will be appriciated! :)
I made a Shell Script to help me do this :)
b="$(grep -n "android.intent.category.LAUNCHER" File.xml | cut -f1 -d:)"
head -n $b File.xml >/tmp/foo.txt
f="$(awk '/activity/{k=$0}END{print k}' /tmp/foo.txt)"
echo $f >> /tmp/file.xml
echo "</activity>" >> /tmp/file.xml
sed -i -e 's/android:/d/g' /tmp/file.xml
xmllint --xpath "string(//activity/@dconfigChanges)" /tmp/file.xml
xmllint --xpath "string(//activity/@dscreenOrientation)" /tmp/file.xml
Since i am using a unix based operating system and not limited to using only xmlstarlet, i made a script that greps
the value "android.intent.category.LAUNCHER" and then uses head
from that file appending all the lines above "android.intent.category.LAUNCHER" to a new text file. to find the first instance of <activity
, the script then uses grep and tail to search from the bottom of the new text file. this returns the full value of <activity android:configChanges="ABC" android:screenOrientation="XXX">
as a string, using echo
and >>
the string is output as an xml file. since the string doesnt contain a </activity>
the script echo
's <activity>
into the file. sed
is used to replace the android:
in each attribute with d
because :
cant be used. using xmllint
we can then find the value of the attributes android:configChanges
and android:screenOrientation
easily.
Output:
ABC
XXX
as expected
Edit:
Changed f="$(grep "<activity" /tmp/foo.txt | tail -$b)"
to f="$(awk '/activity/{k=$0}END{print k}' /tmp/foo.txt)"
the awk command gets the last occurence of activity
in the foo.txt file, it works becuase of the head -n $b File.xml >/tmp/foo.txt
command before, which only takes the first b
lines of the file