是否可以使用 xmlstarlet 将计算属性(即非常量)插入到 XML 文件中?

Is it possible to insert a computed attribute (i.e. non-constant) into an XML file with xmlstarlet?

我有一个这样的 XML 文件:

sources.xml

<?xml version="1.0" encoding="UTF-8"?>
<sources>
  <source>
    <identity id="abc"/>
    <somestuff/>
  </source>
  <source>
    <identity id="def"/>
    <someotherstuff/>
  </source>
</sources>

我想摆脱标签identity并将其属性转移到父节点。换句话说,我需要将输入文件更改为:

<?xml version="1.0" encoding="UTF-8"?>
<sources>
  <source id="abc">
    <somestuff/>
  </source>
  <source id="def">
    <someotherstuff/>
  </source>
</sources>

我试过了:

xmlstarlet edit \
  --insert "//source" --type attr --name "id" --value "identity/@id" \
  --delete "//identity" \
  sources.xml

这不起作用,因为 --value 将其参数理解为常量字符串。

我的问题是:xmlstarlet 是否有可能像 select 操作那样将属性 id 的值计算为 XPATH 表达式?

编辑编号。 1

我找到了朝这个方向完成某件事的方法:

xmlstarlet edit \
  --insert "//source" --type attr --name "id" --value "{PLACE HOLDER}" \
  --update "//source/@id" --expr "../identity/@id" \
  --delete "//identity" \
  sources.xml

但我得到属性 id:

的空值
<?xml version="1.0" encoding="UTF-8"?>
<sources>
  <source id="">
    <somestuff>Hello</somestuff>
  </source>
  <source id="">
    <someotherstuff/>
  </source>
</sources>

表达式../identity/@id有什么问题?

是的,这是可能的,这就是解决方案:

xmlstarlet edit \
  --insert "//source" --type attr --name "id" \
  --update "//source/@id" --expr "string(../identity/@id)" \
  --delete "//identity" \
  sources.xml

--insert 操作不接受 --expr 参数,只有 --value,但 --update 可以。所以我们分两个不同的步骤来完成:首先创建一个空属性,然后用 --expr 更改它的值。

我们还需要使用 XPATH 函数 string() 将作为参数给定的文本节点转换为选项 --expr 的字符串。这在参考资料或教程中没有充分记录。

我 运行 遇到了类似的问题,但是计算属性必须从系统变量中获取。因此,在 OP 的许可下,我想我也会 post 在这里,以供将来参考。

如果

myvar="hello"

这将插入 "hello" 作为 id 属性值:

xmlstarlet edit   --insert "//source" --type attr --name "id"\
   --update "//source/@id" --value "$myvar"   --delete "//identity"   sources.xml

注意:这次我们要使用--value,而不是--expr