我有以下HTML代码:
<textarea name="command" class="setting-input fixed-width" rows="9">1</textarea><textarea name="command" class="setting-input fixed-width" rows="5">2</textarea>
我想解析它以接收这样的输出:
1
2
目前我正在使用:
xmllint --xpath '//textarea[@name="command"]/text()' --html
但每场比赛后都不会附加换行符。
答案 0 :(得分:2)
我做了以下,丑陋的技巧,请随时提供更好的解决方案。
使用以下命令将</textarea>
替换为\n</textarea>
来更改HTML代码:
sed 's/\<\/textarea/\'$'\n\<\\/textarea/g' f
答案 1 :(得分:2)
尝试this patch,它提供2个选项:
--xpath
:与旧的--xpath
相同,节点之间由\n
隔开。
--xpath0
:与旧的--xpath
相同,节点之间由\0
隔开。
测试输入(a.html
):
<textarea name="command" class="setting-input fixed-width" rows="9">1</textarea><textarea name="command" class="setting-input fixed-width" rows="5">2</textarea>
测试命令1:
# xmllint --xpath '//textarea[@name="command"]/text()' --html a.html
测试输出1:
1
2
测试命令2:
# xmllint --xpath0 '//textarea[@name="command"]/text()' --html a.html | xargs -0 -n1
测试输出2:
1
2
答案 2 :(得分:1)
当我从this SO answer收集时,也可以:
varOpexAmount = $(xml).find('d\\:OpexAmount ')
varPreCapexorCapexAmount = $(xml).find('d\\:PreCapexorCapexAmount ')
varSuppCapexAmount = $(xml).find('d\\:SuppCapexAmount')
varBudget = varOpexAmount + varPreCapexorCapexAmount + varSuppCapexAmount;
$("#Budget").append(varBudget);
然后使用
删除输出中的“分隔符”(破折号行)xmllint --shell input.xml <<<'cat //textarea[@name="command"]/text()'
我觉得这样可以让你更接近你想要看到的东西,最初是作为一个人,并且去除你不想要的东西的正则表达式更加明显和精确
但是,在管道中间使用相同的方法可能是不可能的,因为在这种情况下stdin是包含all that whatnot above | sed '/^ -/d'
shell的cat
命令的“here string”。 / p>
同一主题中的另一个建议是使用xmllint
,如果有的话:
xmlstarlet
...并且这仍然可以在管道中正常运行,例如,从xmlstarlet sel -t -v '//textarea[@name="command"]/text()' input.xml
或其他东西。
答案 3 :(得分:0)
这是一个包装脚本,专门用于换行符分隔输出(对于xmllint
的旧版本):
#!/bin/bash
# wrapper script to
# - have newline delimited output on Xpath querys
# - implements --xpath on very old releases
/usr/bin/xmllint --xpath &>/dev/null
implements_xpath=$?
newlines_delimited_xmllint_version=20909
current_version=$(xmllint --version |& awk 'NR==1{print $NF;exit}')
args=( "$@" )
if [[ $@ == *--xpath* ]]; then
# iterate over positional parameters
for ((i=0; i<${#args}; i++)); do
if [[ ${args[i]} == --xpath ]]; then
xpath="${args[i+1]}"
unset args[i+1]
unset args[i]
break
fi
done
if [[ ($implements_xpath==0 && $current_version>=20909) || $file == - || $file == /dev/stdin || $xpath == / || $xpath == string\(* ]]
then
exec /usr/bin/xmllint "$@"
else
exec /usr/bin/xmllint "${args[@]}" --shell <<< "cat $xpath" | sed '1d;$d;s/^ ------- *$//;/^$/d'
fi
else
exec /usr/bin/xmllint "$@"
fi
检查最新修订:https://github.com/sputnick-dev/xmllint
Debian Buster于2020年6月29日发布了2.9.4版本,该版本已发布4年。
Debian测试/实验版为2.9.10,这是固定版本。
另一种在Debian上一个稳定版本中安装2.9.10的方法:https://serverfault.com/a/1022826/120473(不冒使apt
系统崩溃的风险)
答案 4 :(得分:0)
换行符可以合法地出现在 xml 数据中。更可靠的方法是用一个字符来分隔 xpath 结果,保证不会出现在 XML 数据中。 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 的 xmllint
的 merge request 包括添加一个 -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')