换行符可以合法地出现在 xml 数据中。一种更健壮的方法将通过保证不会出现在 XML 数据中的字符来分隔 xpath 结果。通用编码字符集中的空字符U+0000就是这样一个字符。
请注意,分配给空控制字符的代码点 U+0000 是唯一以 Unicode 和 ISO/IEC 10646 编码的字符,在任何 XML 1.0 和 1.1 文档中始终无效。
– https://en.wikipedia.org/wiki/Valid_characters_in_XML
@Cyker 的合并请求包括xmllint
添加一个-xpath0
选项,该选项将用 NUL 分隔 xpath 结果。此功能的新功能请求也已打开。
希望xmllint
很快会获得此功能。
另一个 xpath 命令行工具,xmlstarlet
现在可以被哄骗来实现这个目标。xmlstarlet
目前不支持直接输出 NUL,但我们可以将其设为 output U+FFFF
,与 NUL 一样,保证不会出现在 XML 数据中。(我假设通用编码字符集的 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 ''
注意:我运行了 HTML xmlstarlet fo -H -R
,如@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')