如何通过 xpath 在 macOS 上 select 与 xml 分开匹配

How to select matches separately from xml by xpath on macOS

我想从匹配某个选择器的 XML 文件中获取所有文本内容。

我选择使用 XPath 选择器,因为我已经在我的 Mac 上安装了 xmllint(但它比版本 20909 旧,默认情况下显然具有我想要的行为)

$ xmllint --version
xmllint: using libxml version 20904
   compiled with: Threads Tree Output Push Reader Patterns Writer SAXv1 FTP HTTP DTDValid HTML Legacy C14N Catalog XPath XPointer XInclude ICU ISO8859X Unicode Regexps Automata Expr Schemas Schematron Modules Debug Zlib 

这是我的 xml

<?xml version="1.0" encoding="utf-8"?>
<xml>
  <foo bar="baz">Lorem</foo>
  <foo bar="baz">Ipsum</foo>
  <foo bar="baz">Dolor</foo>
  <foo bar="qux">Sit</foo>
  <foo bar="baz">Amet</foo>
</xml>

我想获取具有某个属性值的foo元素的每个文本内容

$ xmllint --xpath '//foo[@bar="baz"]/text()' my.xml
LoremIpsumDolorAmet

输出不是换行分隔的,似乎也不是 NUL 分隔的:

$ xmllint --xpath '//foo[@bar="baz"]//text()' my.xml | od -A n -t x1
           4c  6f  72  65  6d  49  70  73  75  6d  44  6f  6c  6f  72  41
           6d  65  74  

如何使用 macOS 呈现输出,使匹配项之间用换行符分隔?

可以用xpath --shell按如下方式完成。 如果XML文件不是太大,可以优化加载到内存中。

cnt=$(xmllint --xpath 'count(//foo[@bar="baz"])' test.xml)
(for i in $(seq 1 $cnt); do echo "cat //foo[@bar='baz'][$i]/text()"; done) | xmllint --shell test.xml | grep -Ev '\/ [<>]( cat)?| -------'

结果:

Lorem
Ipsum
Dolor
Amet

最后没有 grep 它会产生

/ > cat //foo[@bar='baz'][1]/text()
 -------
Lorem
/ > cat //foo[@bar='baz'][2]/text()
 -------
Ipsum
/ > cat //foo[@bar='baz'][3]/text()
 -------
Dolor
/ > cat //foo[@bar='baz'][4]/text()
 -------
Amet
/ >

值得添加到答案中的不同版本

cnt=4; (for i in $(seq 1 $cnt); do echo "cd //foo[@bar='baz'][$i]/text()"; echo "cat"; done) | xmllint --shell test.xml | grep -Ev ' > (cat|cd)?'

没有 grep

/ > cd //foo[@bar='baz'][1]/text()
text > cat
Lorem
text > cd //foo[@bar='baz'][2]/text()
text > cat
Ipsum
text > cd //foo[@bar='baz'][3]/text()
text > cat
Dolor
text > cd //foo[@bar='baz'][4]/text()
text > cat
Amet
text >