我想在XML输入的某些变体中插入其他元素。该脚本试图演示输入,并且尝试将代码插入现有XML。可以看出,修改a.xml
可以得到预期的输出。但是在b.xml
和c.xml
中,结果是虚假的。在b.xml
中,更改现有的<c/>
,并创建<b/>
的另一个块。在c.xml
中,结果是d=""
被分配了两次。
应该只有一个<a><b>
和几个<c>
。
有什么想法要实现吗?
#!/bin/bash
# insert <a><b><c d="2"/>
set -e
td=`mktemp --directory --tmpdir=/dev/shm XXX`
trap "rm -rf '${td}'" EXIT
xmlstarlet --version
pushd "${td}"
cat > a.xml <<_EOX_
<a>
</a>
_EOX_
cat > b.xml <<_EOX_
<a>
<b>
<c/>
</b>
</a>
_EOX_
cat > c.xml <<_EOX_
<a>
<b>
<c d="1"/>
</b>
</a>
_EOX_
for i in *.xml
do
echo "$i"
cat "$i" | \
xmlstarlet ed -O \
-s 'a' -t elem -n b \
-s 'a/b' -t elem -n c \
-i 'a/b/c' -t attr -n d -v '2' |
xmlstarlet fo -o || echo "$?"
done
这将产生以下输出:
1.6.1
compiled against libxml2 2.9.7, linked with 20907
compiled against libxslt 1.1.32, linked with 10132
/dev/shm/tpX ~/work
a.xml
<a>
<b>
<c d="2"/>
</b>
</a>
37
b.xml
<a>
<b>
<c d="2"/>
<c d="2"/>
</b>
<b>
<c d="2"/>
</b>
</a>
80
c.xml
-:3.19: Attribute d redefined
<c d="1" d="2"/>
^
2
答案 0 :(得分:0)
问题在于您需要告诉您要更改的节点。
仅在b
中不存在b
时添加子项a
:
-s "/a[not(b)]" -t elem -n "b"
在c
中添加新的孩子a/b
:
-s "/a/b[not(c)]" -t elem -n "c"
向最后添加的节点d
添加属性c
:
-s "/a/b/c[last()]" -t attr -n "d" -v "2"
因此完整的命令现在显示为:
xmlstarlet ed -O \
-s "/a[not(b)]" -t elem -n "b" \
-s "/a/b" -t elem -n "c" \
-s "/a/b/c[last()]" -t attr -n "d" -v "2"
在这里,我们使用not()
函数来表示我们只想选择不包含该特定项目的节点。
有用的链接: