xmlstarlet 添加具有命名空间和属性的元素
xmlstarlet add element with namespace and attributes
我正在尝试将具有名称空间和属性的节点添加到 xml,但如果我尝试在 xmlstarlet 的一次执行中将其作为多个命令来执行,则会失败:
<?xml version="1.0"?>
<levela xmlns:xi="http://www.w3.org/2001/XInclude">
<levelb>
</levelb>
</levela>
xmlstarlet ed -L -s /levela/levelb -t elem -n xi:input -i //xi:input -t attr -n "href" -v "aHref" file.xml
我正在尝试获取:
<?xml version="1.0"?>
<levela xmlns:xi="http://www.w3.org/2001/XInclude">
<levelb>
<xi:input href="aHref"/>
</levelb>
</levela>
但是没有添加属性。所以我得到:
<?xml version="1.0"?>
<levela xmlns:xi="http://www.w3.org/2001/XInclude">
<levelb>
<xi:input/>
</levelb>
</levela>
如果我 运行 它像这样执行两次,它就会工作:
xmlstarlet ed -L -s /levela/levelb -t elem -n xi:input file.xml
xmlstarlet ed -L -i //xi:input -t attr -n "href" -v "aHref" file.xml
如果我添加一个没有命名空间的标签,它也有效,例如:
xmlstarlet ed -L -s /levela/levelb -t elem -n levelc -i //levelc -t attr -n "href" -v "aHref" file.xml
<?xml version="1.0"?>
<levela xmlns:xi="http://www.w3.org/2001/XInclude">
<levelb>
<levelc href="aHref"/>
</levelb>
</levela>
我做错了什么?为什么它不适用于命名空间?
您似乎无法将属性和属性值插入命名空间节点...也许更聪明的人可以想出别的办法,但至少在这种情况下,我能解决这个问题的唯一方法是这个:
xmlstarlet ed -N xi="http://www.w3.org/2001/XInclude" --subnode "//levela/levelb" \
--type elem -n "xi:input" --insert "//levela/levelb/*" --type attr --name "href"\
--value "aHref" file.xml
这样做就可以了:
xmlstarlet edit \
-s '/levela/levelb' -t elem -n 'xi:input' \
-s '$prev' -t attr -n 'href' -v 'aHref' \
file.xml
xmlstarlet edit
代码可以使用方便的 $prev
(又名
$xstar:prev
) 变量引用最多创建的节点
最近的 -i (--insert)
、-a (--append)
或 -s (--subnode)
选项。
$prev
的例子在
doc/xmlstarlet.txt 和
源代码的
examples/ed-backref*.
可以使用 -i
、-a
或 -s
添加属性。
What am I doing wrong? Why doesn't it work with the namespace?
更新 2022-04-15
您使用的 -i '//xi:input' …
语法是完全合乎逻辑的。身为你的
拥有 2 个替代命令表明它是命名空间 xi
触发遗漏并且在 edInsert
函数中有一个提示
源代码的
src/xml_edit.c
它说 NULL /* TODO: NS */
。
当你与 xmlstarlet
合作过一些
是时候接受(或不接受)它的限制了;在这种情况下
$prev
反向引用很有用。我不希望 TODO
尽快离开。
(结束更新)
嗯,我认为 xmlstarlet edit
将节点命名视为用户
责任,如下例所示,
printf '<v/>' |
xmlstarlet edit --omit-decl \
-s '*' -t elem -n 'undeclared:qname' -v 'x' \
-s '*' -t elem -n '!--' -v ' wotsinaname ' \
-s '$prev' -t attr -n ' "" ' -v '' \
-s '*' -t elem -n ' <&> ' -v 'harrumph!'
输出显然不是XML:
<v>
<undeclared:qname>x</undeclared:qname>
<!-- "" =""> wotsinaname </!-->
< <&> >harrumph!</ <&> >
</v>
如果要缩进新元素,例如:
xmlstarlet edit \
-s '/levela/levelb' -t elem -n 'xi:input' \
--var newnd '$prev' \
-s '$prev' -t attr -n 'href' -v 'aHref' \
-a '$newnd' -t text -n ignored -v '' \
-u '$prev' -x '(//text())[1][normalize-space()=""]' \
file.xml
-x
XPath 表达式获取提供的第一个文本节点
只包含空格,即 levela
的第一个子节点。
--var name xpath
选项定义 xmlstarlet edit
中提到了变量
doc/xmlstarlet.txt
但不在用户指南中。
我用的是xmlstarlet
版本1.6.1.
我正在尝试将具有名称空间和属性的节点添加到 xml,但如果我尝试在 xmlstarlet 的一次执行中将其作为多个命令来执行,则会失败:
<?xml version="1.0"?>
<levela xmlns:xi="http://www.w3.org/2001/XInclude">
<levelb>
</levelb>
</levela>
xmlstarlet ed -L -s /levela/levelb -t elem -n xi:input -i //xi:input -t attr -n "href" -v "aHref" file.xml
我正在尝试获取:
<?xml version="1.0"?>
<levela xmlns:xi="http://www.w3.org/2001/XInclude">
<levelb>
<xi:input href="aHref"/>
</levelb>
</levela>
但是没有添加属性。所以我得到:
<?xml version="1.0"?>
<levela xmlns:xi="http://www.w3.org/2001/XInclude">
<levelb>
<xi:input/>
</levelb>
</levela>
如果我 运行 它像这样执行两次,它就会工作:
xmlstarlet ed -L -s /levela/levelb -t elem -n xi:input file.xml
xmlstarlet ed -L -i //xi:input -t attr -n "href" -v "aHref" file.xml
如果我添加一个没有命名空间的标签,它也有效,例如:
xmlstarlet ed -L -s /levela/levelb -t elem -n levelc -i //levelc -t attr -n "href" -v "aHref" file.xml
<?xml version="1.0"?>
<levela xmlns:xi="http://www.w3.org/2001/XInclude">
<levelb>
<levelc href="aHref"/>
</levelb>
</levela>
我做错了什么?为什么它不适用于命名空间?
您似乎无法将属性和属性值插入命名空间节点...也许更聪明的人可以想出别的办法,但至少在这种情况下,我能解决这个问题的唯一方法是这个:
xmlstarlet ed -N xi="http://www.w3.org/2001/XInclude" --subnode "//levela/levelb" \
--type elem -n "xi:input" --insert "//levela/levelb/*" --type attr --name "href"\
--value "aHref" file.xml
这样做就可以了:
xmlstarlet edit \
-s '/levela/levelb' -t elem -n 'xi:input' \
-s '$prev' -t attr -n 'href' -v 'aHref' \
file.xml
xmlstarlet edit
代码可以使用方便的 $prev
(又名
$xstar:prev
) 变量引用最多创建的节点
最近的 -i (--insert)
、-a (--append)
或 -s (--subnode)
选项。
$prev
的例子在
doc/xmlstarlet.txt 和
源代码的
examples/ed-backref*.
可以使用 -i
、-a
或 -s
添加属性。
What am I doing wrong? Why doesn't it work with the namespace?
更新 2022-04-15
您使用的 -i '//xi:input' …
语法是完全合乎逻辑的。身为你的
拥有 2 个替代命令表明它是命名空间 xi
触发遗漏并且在 edInsert
函数中有一个提示
源代码的
src/xml_edit.c
它说 NULL /* TODO: NS */
。
当你与 xmlstarlet
合作过一些
是时候接受(或不接受)它的限制了;在这种情况下
$prev
反向引用很有用。我不希望 TODO
尽快离开。
(结束更新)
嗯,我认为 xmlstarlet edit
将节点命名视为用户
责任,如下例所示,
printf '<v/>' |
xmlstarlet edit --omit-decl \
-s '*' -t elem -n 'undeclared:qname' -v 'x' \
-s '*' -t elem -n '!--' -v ' wotsinaname ' \
-s '$prev' -t attr -n ' "" ' -v '' \
-s '*' -t elem -n ' <&> ' -v 'harrumph!'
输出显然不是XML:
<v>
<undeclared:qname>x</undeclared:qname>
<!-- "" =""> wotsinaname </!-->
< <&> >harrumph!</ <&> >
</v>
如果要缩进新元素,例如:
xmlstarlet edit \
-s '/levela/levelb' -t elem -n 'xi:input' \
--var newnd '$prev' \
-s '$prev' -t attr -n 'href' -v 'aHref' \
-a '$newnd' -t text -n ignored -v '' \
-u '$prev' -x '(//text())[1][normalize-space()=""]' \
file.xml
-x
XPath 表达式获取提供的第一个文本节点
只包含空格,即 levela
的第一个子节点。
--var name xpath
选项定义 xmlstarlet edit
中提到了变量
doc/xmlstarlet.txt
但不在用户指南中。
我用的是xmlstarlet
版本1.6.1.