换行符可以合法地出现在 xml 数据中。一种更健壮的方法将通过保证不会出现在 XML 数据中的字符来分隔 xpath 结果。 Null character,Universal Coded Character Set中的U+0000,就是这样一个字符。
注意代码点U+0000,分配给空控件
字符,是唯一以 Unicode 和 ISO/IEC 10646 编码的字符
这在任何 XML 1.0 和 1.1 文档中始终无效。
– https://en.wikipedia.org/wiki/Valid_characters_in_XML
@Cyker 的merge request 为xmllint 添加了一个-xpath0 选项,该选项将用NUL 分隔xpath 结果。 A new feature request 这个功能也被打开了。
希望xmllint 能尽快获得此功能。
另一个 xpath 命令行工具,xmlstarlet,现在可以用来实现这个目标。 xmlstarlet目前不支持直接输出NUL,但是我们可以让它输出U+FFFF,和NUL一样,保证不会出现在XML数据中。 (我假设Universal Coded Character Set 是UTF-8 编码。)然后我们只需要将U+FFFF 转换为U+0000,我们就会得到NUL 分隔的xpath 结果。
在以下示例中,我将使用以下部分 html 文件。这是来自问题的相同数据,除了我添加了换行符用于测试目的。
cat > data.html <<'EOF'
<textarea name="command" class="setting-input fixed-width" rows="9">1
newline</textarea>
<textarea name="command" class="setting-input fixed-width" rows="5">2
newline</textarea>
EOF
下面是如何使用xmlstarlet 和perl 单行符来用NUL 分隔xpath 结果:
xmlstarlet fo -H -R data.html \
| xmlstarlet sel -t -m '//textarea[@name="command"]' -v '.' -o $'\uffff' \
| perl -C -0xFFFF -l0 -pe ''
注意:我通过xmlstarlet fo -H -R 运行HTML,如@TheDudeAbides 回答中所示。
现在 xpath 结果由 NUL 分隔,我们可以在 xargs -0 的帮助下处理结果。示例:
xmlstarlet fo -H -R data.html \
| xmlstarlet sel -t -m '//textarea[@name="command"]' -v '.' -o $'\uffff' \
| perl -C -0xFFFF -l0 -pe '' \
| xargs -0 -n 1 printf '%q\n'
结果:
'1 '$'\n'' newline'
'2 '$'\n'' newline'
或将其加载到 bash 数组中:
mapfile -t -d '' a < <(
xmlstarlet fo -H -R data.html \
| xmlstarlet sel -t -m '//textarea[@name="command"]' -v '.' -o $'\uffff' \
| perl -C -0xFFFF -l0 -pe ''
)
declare -p a
结果:
declare -a a=([0]=$'1 \n newline' [1]=$'2 \n newline')