我需要在 XML 文件中将某些指定标签中的特定字符串替换为标签中嵌入的其他字符串。
搜索每次出现 , 的示例,仅当它在标签内(在其他标签内)时才an example
需要替换为:<b>a test</b>
<a> ... </a>
- 输入示例:
<c>This is an example. <a>This is an example;</a></c>
- 期望的输出:
<c>This is an example. <a>This is <b>a test;</b></a></c>
答案1
看来你想要
- 从XML 文档中的节点
an example;
值中删除文本,并且/c/a
/c/a
向名为 的节点添加一个b
值为 的子节点a test;
。
xmlstarlet
您可以在 shell 中轻松执行此操作:
xmlstarlet ed -u '/c/a' -x 'substring-before(text(), "an example;")' file.xml |
xmlstarlet ed -s '/c/a' -t elem -n 'b' -v 'a test;'
xmlstarlet
问题中示例文档的第一次调用将产生以下输出,其中一些文本从/c/a
节点的值中删除:
<?xml version="1.0"?>
<c>This is an example. <a>This is </a></c>
第二次调用采用此修改后的文档并通过引入节点生成以下内容/c/a/b
:
<?xml version="1.0"?>
<c>This is an example. <a>This is <b>a test;</b></a></c>
这些xmlstarlet
调用可以组合成单个命令。下面,我使用了长选项,也用于--inplace
原始文档的就地编辑(这仅用于说明,您应该--inplace
先运行 without 以确定转换是否有效):
xmlstarlet ed --inplace \
--update '/c/a' -x 'substring-before(text(), "an example;")' \
--subnode '/c/a' -t elem -n 'b' -v 'a test;' file.xml
将上述内容概括为对a
包含文本的任何节点执行两次编辑an example;
(这是问题中实际要求的内容):
xmlstarlet ed \
--var paths '//a[contains(text(), "an example;")]' \
--update '$paths' -x 'substring-before(text(), "an example;")' \
--subnode '$paths' -t elem -n 'b' -v 'a test;' file.xml
这里唯一的新事物是我们首先将要编辑的所有节点的路径存储在内部变量中$paths
。然后我们在--update
和修改中引用这些路径--subnode
。