如何在 XML 文件中取消嵌入指定标记内的标记字符链

如何在 XML 文件中取消嵌入指定标记内的标记字符链

在 XML 文件中,用于取消嵌入指定标记内的标记字符链的 xmlstarlet 命令是什么?

示例:搜索标记的每个出现位置<b>,仅当它在标记内时才需要删除<c> ... </c>

  • 输入示例:
    <c>This is <b>an example</b>. <a>This is <b>a test;</b></a></c>
    
  • 期望的输出:
    <c>This is an example. <a>This is <b>a test;</b></a></c>
    

为了概括起见,我保留示例中的第二句话,即

<a>This is <b>a test;</b></a>

但如果这是一个问题,则可以忽略。

答案1

这可以通过--update将节点的值复制//c/b到其父节点中,然后--delete删除现在不需要的b节点来完成。

这与我在最后采取的方法类似我之前对你的问题的回答之一,我首先创建一个内部xmlstarlet变量,用于保存我们需要处理的所有节点的集合,然后处理这些节点。我们这样做是为了更轻松地访问同一组节点以进行更新和删除操作。在之前的回答中,这是必要的,但这里只是为了可读性。

xmlstarlet ed \
    --var 'path' '//c/b' \
    --update '$path/../text()[1]' --expr 'concat(., $path/text())' \
    --delete '$path' file.xml

这里值得注意的是,更新并不针对b节点的父节点,而是针对父节点的第一个文本值, text()[1].示例文档中节点父节点的第一个文本值//c/b是字符串This is。这第二文本值位于节点.之后b。如果我们[1]最后选择没有,我们最终会得到

<?xml version="1.0"?>
<c>This is an example. an example<a>This is <b>a test;</b></a></c>

也就是说,该字符串an example将被插入到c节点的两个文本值之后。

现在,我们得到

<?xml version="1.0"?>
<c>This is an example. <a>This is <b>a test;</b></a></c>

相关内容