如何使用 XMLStarlet 查找第二个文件中的值

问题描述 投票:0回答:1

假设我们有这个简单的 xmlstarlet 脚本:

find . -iname '*.xml' | xargs xmlstarlet sel -N z="abc.com/article/1.0/" \
  -t -m "/z:ad" -i "/*/z:status='PUBLIC'" -v "/*/z:id" -b -n | grep -v ^$

这只是遍历所有 XML 文件(从我执行此脚本的目录开始)并打印出 status=PUBLIC 的记录 ID。

现在我想查找另一个文件中的另一个值,并且该文件具有简单路径

/path/ID.xml

我怎样才能做到这一点?

ChatGPT告诉我这个解决方案,我尝试了几次迭代,没有成功。

find . -iname '*.xml' | xargs xmlstarlet sel -N z="abc.com/article/1.0/" \ 
  -t -m "/z:ad" -i "/*/z:status='PUBLIC'" -v "/*/z:id" -o ',' \
  --var name="$(xmlstarlet sel -N z="abc.com/article/1.0/" -t -v '/*/z:name' /PATH/TO/SECOND/FILE.xml)" \
  -v '$name' -b -n | grep -v ^$

它不会抛出任何错误,但不会打印第二个文件中的 name 值:

123412341234,
838373847387,
828278388222,

如何使用单行命令来实现这一点?我不想执行脚本。

xmlstarlet
1个回答
0
投票

我真幸运!没有任何数据可供查看,我可以随意猜测,但有些事情 像下面这样应该有效:

# shellcheck  shell=sh  disable=SC2016
find . -type f -iname '*.xml' -exec xmlstarlet select \
  -N z='abc.com/article/1.0/' --text \
  -t --var ofs -o ',' -b \
     --var ors -n -b \
     --var infnm -f -b \
     -m '/*[z:status="PUBLIC"]/z:id' \
       --var pubid='.' \
       --var pubnm='document("/path/ID.xml")/*[z:id=$pubid]/z:name' \
       -v 'concat($infnm,$ofs,$pubid,$ofs,$pubnm,$ors)' \
  {} +

  • xargs
    可以调用时,为什么还要麻烦
    grep
    find
    xmlstarlet select
    具有与命令一样多的文件名 (
    {} +
    ) 线可以容纳(
    select --help
    [ <xml-file> ... ]
    ,回忆一下), 并根据需要重复
  • 使用 XPath 谓词 来表达
    status="PUBLIC"
    状况
  • 使用 XSLT
    document()
    函数 在外部 XML 文件中查找当前
    PUBLIC
    id 的名称
  • 使用XPath
    concat
    函数输出 一条记录
  • 不要忘记
    select
    -T
    (又名
    --text
    )明文选项 输出
  • 如果没有输入与搜索条件匹配,则不会生成任何输出
  • XSLT 变量
    ofs
    ors
    保存输出字段/记录 分隔符,
    infnm
    当前输入文件/URL 的名称 (
    inputFile
    是预定义的,但未记录)
© www.soinside.com 2019 - 2024. All rights reserved.