在 zsh 或 bash 中使用 XMLStarlet 解析 XML 的速度效率

Speed efficiency in parsing XML with XMLStarlet in zsh or bash

我们有一个相当复杂的 zsh 应用程序,它使用 XML 文件来存储其配置和数据。当前读取和写入这些文件的方法是使用 xmlstarlet.

当更新一个文件时,我们将整个 XML 多次通过管道传输,对于我们接触的每个属性或元素一次,如下所示:

cat "$config" \
| xml_addSubnode              "/a/b/c"                 "foo" \
| xml_createOrUpdateAttribute "/a/b/c/foo[last()]"     "attr1"  "zzzz" \
| xml_createOrUpdateAttribute "/a/b/c/foo[last()]"     "attr2"  "wwww" \
\
| xml_addSubnode              "/a/b/c/foo[last()]"     "attr3" \
| xml_createOrUpdateAttribute "/a/b/c/foo[last()]/bar" "attr4"  "zzzz" \
| xml_createOrUpdateAttribute "/a/b/c/foo[last()]/bar" "attr5"  "kkkk" \
\
| xml_update "$config"

每次分别调用xml将属性读入shell个变量:

local foo="$(xml_value "$xpath" "$config")"
local bar="$(xml_value "$xpath" "$config")"
...

效用函数归结如下:

xml_addSubnode() {
    ...
    cat | xml ed -s "$elementXPath" -t elem -n "$element"
}

xml_createOrUpdateAttribute()
{
    ...
    cat | xml ed --update ... --insert ...
}

xml_value()
{
    ...
    xml sel -t -v "$xPath" "$xmlFile"
}

xml_update()
{
    ...
    cat > "$file"
}

此代码在功能上运行良好,但显然性能很糟糕。

如何使这段代码更有效率?还有哪些其他方法可以使用 zsh 或 bash 解析 XML 以产生更快的执行速度?

使用另一种格式也是一种选择,尽管这需要一些迁移工作。我知道 jq JSON 解析器,但用法与 xmlstarlet 类似,如果我采用相同的方法,我不会有太多收获,对吧?

程序在FreeBSD上运行。

您可以使用 xmlstarlet 一次性完成所有更新,这比调用它 6 次要快得多:

#!/usr/bin/env zsh

cat test.xml
print -- --------
xmlstarlet ed \
           -s '/a/b/c' -t elem -n foo \
           -s '/a/b/c/foo[last()]' -t attr -n attr1 -v zzzz \
           -s '/a/b/c/foo[last()]' -t attr -n attr2 -v wwww \
           -s '/a/b/c/foo[last()]' -t elem -n bar \
           -s '/a/b/c/foo[last()]/bar' -t attr -n attr3 -v zzzz \
           -s '/a/b/c/foo[last()]/bar' -t attr -n attr4 -v kkkk \
           test.xml

示例:

$ ./test.sh
<?xml version="1.0"?>
<a><b><c/></b></a>
--------
<?xml version="1.0"?>
<a>
  <b>
    <c>
      <foo attr1="zzzz" attr2="wwww">
        <bar attr3="zzzz" attr4="kkkk"/>
      </foo>
    </c>
  </b>
</a>