从元素的特定子元素获取元素的属性值

Getting attribute value of an element from its specific sub-element

我正在尝试在我的 Mac 上使用 xmlstarlet 从元素的子元素中获取元素的属性值,这里是一个示例

我有一个 xml 文件,其中包含很多这样的元素,android:configChanges 等属性因元素而异:

<activity android:configChanges="ABC" android:screenOrientation="XXX">
        <intent-filter>
            <action android:name="XYZ"/>
            <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>
</activity>

问题是 category android:name 的值对于此元素是唯一的,即 android.intent.category.LAUNCHER

有没有办法使用 xmllint 或 xmlstarlet 我 运行

xmlstarlet <magic code> <filename>

如果提供 /activity/intent-filter/category android:name = "android.intent.category.LAUNCHER"

<magic code> 应该能够分辨出 android:configChangesandroid:screenOrientation 的值

因此,deisred 输出应该是

android:configChanges="ABC" android screenOrientation="XXX"

到目前为止,我唯一知道的是如何使用

从特定子元素中获取其他子元素的值
xmlstarlet sel -t -c "/activity/intent-filter/category[@android:name=android.intent.category.LAUNCHER]/*" file.xml

哪个returns

<action android:name="XYZ"/>
<category android:name="android.intent.category.LAUNCHER"/>

如有任何帮助,我们将不胜感激! :)

我制作了一个 Shell 脚本来帮助我做到这一点 :)

b="$(grep -n "android.intent.category.LAUNCHER" File.xml | cut -f1 -d:)"
head -n $b File.xml >/tmp/foo.txt
f="$(awk '/activity/{k=[=10=]}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

由于我使用的是基于 unix 的操作系统,并且不限于仅使用 xmlstarlet,因此我制作了一个脚本 greps 值 "android.intent.category.LAUNCHER" 然后使用 head 从该文件中将 "android.intent.category.LAUNCHER" 以上的所有行附加到一个新的文本文件中。为了找到 <activity 的第一个实例,脚本然后使用 grep 和 tail 从新文本文件的底部开始搜索。 returns <activity android:configChanges="ABC" android:screenOrientation="XXX"> 的完整值作为字符串,使用 echo>> 字符串输出为 xml 文件。因为字符串不包含 </activity> 脚本 echo<activity> 到文件中。 sed用于将每个属性中的android:替换为d,因为:不能使用。使用 xmllint 我们可以轻松找到属性 android:configChangesandroid:screenOrientation 的值。

输出:

ABC
XXX

符合预期

编辑:

f="$(grep "<activity" /tmp/foo.txt | tail -$b)" 更改为 f="$(awk '/activity/{k=[=29=]}END{print k}' /tmp/foo.txt)" awk 命令获取 foo.txt 文件中最后一次出现的 activity,由于 head -n $b File.xml >/tmp/foo.txt 命令,它可以工作之前,它只占用文件

的前 b