You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用xmlstarlet提取XML值时如何为缺失元素返回对应空值

问题描述

我现在正在处理名为extract.BCBR.job.xml的XML文件,当前用如下xmlstarlet命令提取APPL_TYPE为"PS8"的JOB节点下,NAME属性为%%PS8-PROCESSES-J1-P2-PROCESSNAME的VARIABLE元素的VALUE属性值:

xmlstarlet sel -t -m '//JOB[@APPL_TYPE="PS8"]/VARIABLE[@NAME="%%PS8-PROCESSES-J1-P2-PROCESSNAME"]' -v './@VALUE' -n ~testhwa/extract.BCBR.job.xml >> /tmp/prcsname_2

该命令在目标元素存在时可以正常运行,但我的需求是:当匹配的JOB节点下不存在目标VARIABLE元素时,也向输出文件/tmp/prcsname_2返回空值(空行)。我后续会用for循环遍历该输出文件700余次,空值可以支撑后续的if-else条件判断逻辑。

示例输入

<?xml version='1.0' encoding='UTF-8' ?>
<!-- XML Utils Details: version 9.0.0. Exported at 20210503-130101 by rfernan9 from server DEV -->
<DEFTABLE xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Folder.xsd">
    <FOLDER DATACENTER="DEV" FOLDER_NAME="DVFINAL" LAST_UPLOAD="20101206223355UTC" PLATFORM="UNIX" REAL_FOLDER_ID="0" TYPE="1" USED_BY_CODE="0" VERSION="919">
<JOB
            APPLICATION="DVPeopleSoft_Finance"
            APPL_FORM="PEOPLESOFT"
            APPL_TYPE="PS8"
            APPL_VER="8"
            APR="1"
            AUG="1"
            AUTOARCH="0"
            CM_VER="6.1.01"
            CONFIRM="0"
            CREATED_BY="prichar3"
            CREATION_DATE="20101206"
            CREATION_TIME="163137"
            CREATION_USER="prichar3"
            CRITICAL="0"
            CYCLIC="0"
            CYCLIC_TOLERANCE="0"
            CYCLIC_TYPE="C"
            DAYSCAL="02/05/2009"
            DAYS_AND_OR="O"
            DEC="1"
            DESCRIPTION="origtasktype=Command, &quot;Daily Close GL Reports &quot;"
            FEB="1"
            IND_CYCLIC="T"
            INTERVAL="00001M"
            JAN="1"
            JOBISN="3"
            JOBNAME="PFD_GLR01DLY_PF_RPTBOOK-01A"
            JUL="1"
            JUN="1"
            MAR="1"
            MAXDAYS="0"
            MAXRERUN="0"
            MAXRUNS="0"
            MAXWAIT="0"
            MAY="1"
            MEMNAME="PFD_GLR01DLY_PF_RPTBOOK-01A"
            MULTY_AGENT="N"
            NODEID="FS90QAT1"
            NOV="1"
            OCT="1"
            PARENT_FOLDER="DVPeopleSoft_Finance"
            RETRO="0"
            RUN_AS="CONTROLM"
            SEP="1"
            SHIFT="Ignore Job"
            SHIFTNUM="+00"
            SUB_APPLICATION="PFD_GLR01DLY"
            SYSDB="0"
            TASKTYPE="Dummy"
            USE_INSTREAM_JCL="N"
            WEEKSCAL="03/05/2009">
            <INCOND AND_OR="A" NAME="start_FS90QAT#PFD_GLR01DLY-OK" ODATE="ODAT"/>
            <OUTCOND NAME="FS90QAT#PFD_GLR01DLY_PF_RPTBOOK-01A-OK" ODATE="ODAT" SIGN="+"/>
            <VARIABLE NAME="%%PS8-CON_PROFILE" VALUE="QAT"/>
            <VARIABLE NAME="%%PS8-USERID" VALUE="CONTROLM"/>
            <VARIABLE NAME="%%PS8-RUNCONTROLID" VALUE="GLR01DLY1"/>
            <VARIABLE NAME="%%PS8-PRCSTYPE" VALUE="nVision-ReportBook"/>
            <VARIABLE NAME="%%PS8-PRCSNAME" VALUE="RPTBK01"/>
            <VARIABLE NAME="%%PS8-APOUT" VALUE="1"/>
        </JOB>

<JOB
            APPLICATION="DVPeopleSoft_Finance"
            APPL_FORM="PEOPLESOFT"
            APPL_TYPE="PS8"
            APPL_VER="8"
            APR="1"
            AUG="1"
            AUTOARCH="0"
            CM_VER="6.1.01"
            CONFIRM="0"
            CREATED_BY="stamilar"
            CREATION_DATE="20131106"
            CREATION_TIME="110438"
            CREATION_USER="stamilar"
            CRITICAL="0"
            CYCLIC="0"
            CYCLIC_TOLERANCE="0"
            DAYS="ALL"
            DAYS_AND_OR="O"
            DEC="1"
            DESCRIPTION="origtasktype=Command, &quot;Pcard paycycle USA&quot;"
            FEB="1"
            INTERVAL="00001M"
            JAN="1"
            JOBISN="1"
            JOBNAME="PFD_SP01DLY_AP_PF_PC_USA"
            JUL="1"
            JUN="1"
            MAR="1"
            MAXDAYS="0"
            MAXRERUN="0"
            MAXRUNS="0"
            MAXWAIT="0"
            MAY="1"
            MEMLIB="Not in use for PeopleSoft jobs"
            MEMNAME="PFD_SP01DLY_AP_PF_PC_USA"
            MULTY_AGENT="N"
            NOV="1"
            OCT="1"
            PARENT_FOLDER="DVPeopleSoft_Finance_AP"
            RETRO="0"
            RUN_AS="BATCH"
            SEP="1"
            SHIFT="Ignore Job"
            SHIFTNUM="+00"
            SUB_APPLICATION="PFD_SP01DLY_AP_PF"
            SYSDB="0"
            TASKTYPE="Job"
            TIMEFROM="1900"
            USE_INSTREAM_JCL="N"
            WEEKDAYS="ALL">
            <OUTCOND NAME="PFD_SP01DLY_AP_PF_PC_USA-OK" ODATE="ODAT" SIGN="+"/>
            <VARIABLE NAME="%%PS8-CON_PROFILE" VALUE="FS90QAT"/>
            <VARIABLE NAME="%%PS8-USERID" VALUE="BATCH"/>
            <VARIABLE NAME="%%PS8-RUNCONTROLID" VALUE="PC_USA"/>
            <VARIABLE NAME="%%PS8-SERVERNAME" VALUE="PSUNX"/>
            <VARIABLE NAME="%%PS8-PRCSTYPE" VALUE="PSJob"/>
            <VARIABLE NAME="%%PS8-APOUT" VALUE="1"/>
            <VARIABLE NAME="%%PS8-OUTDESTFORMAT" VALUE="HTM"/>
            <VARIABLE NAME="%%PS8-OUTDESTTYPE" VALUE="Web"/>
            <VARIABLE NAME="%%PS8-JOBNAME" VALUE="APPCJOB"/>
            <VARIABLE NAME="%%PS8-DESCRIPTION" VALUE="PayCycle Job"/>
            <VARIABLE NAME="%%PS8-PROCESSES-J1-P1-DESCRIPTION" VALUE="PayCycle Job"/>
            <VARIABLE NAME="%%PS8-PROCESSES-J1-P1-PROCESSNAME" VALUE="APPCJOB"/>
            <VARIABLE NAME="%%PS8-PROCESSES-J1-P1-PROCESSTYPE" VALUE="PSJob"/>
            <VARIABLE NAME="%%PS8-PROCESSES-J1-P2-DESCRIPTION" VALUE="Pay Cycle Process"/>
            <VARIABLE NAME="%%PS8-PROCESSES-J1-P2-PROCESSNAME" VALUE="AP_APY2015"/>
            <VARIABLE NAME="%%PS8-PROCESSES-J1-P2-PROCESSTYPE" VALUE="Application Engine"/>
            <VARIABLE NAME="%%PS8-PROCESSES-J1-P3-DESCRIPTION" VALUE="Pay Cycle Job Finalize"/>
            <VARIABLE NAME="%%PS8-PROCESSES-J1-P3-PROCESSNAME" VALUE="ZPV_FINALIZE"/>
            <VARIABLE NAME="%%PS8-PROCESSES-J1-P3-PROCESSTYPE" VALUE="Application Engine"/>
        </JOB>

期望输出

<空行>
AP_APY2015

解决方案

xmlstarlet原生支持该需求,只需调整匹配逻辑即可实现。

修改后命令

xmlstarlet sel -t -m '//JOB[@APPL_TYPE="PS8"]' \
  -v './VARIABLE[@NAME="%%PS8-PROCESSES-J1-P2-PROCESSNAME"]/@VALUE' \
  -n ~testhwa/extract.BCBR.job.xml >> /tmp/prcsname_2

逻辑说明

  • 原命令的匹配维度是VARIABLE节点,不存在目标VARIABLE的JOB会被直接过滤,无任何输出
  • 调整后匹配维度改为所有APPL_TYPE="PS8"的JOB节点,每个JOB都会触发一次输出逻辑:存在目标VARIABLE时输出其VALUE属性值,不存在时输出空字符串
  • 末尾的-n参数会为每一次输出追加换行,空字符串加换行就对应所需的空行

兼容性优化(可选)

如果使用的xmlstarlet版本较低,匹配为空时不输出空字符串,可以改用带显式判断的XPath表达式,逻辑更稳妥:

xmlstarlet sel -t -m '//JOB[@APPL_TYPE="PS8"]' \
  -v 'if (./VARIABLE[@NAME="%%PS8-PROCESSES-J1-P2-PROCESSNAME"]) then ./VARIABLE[@NAME="%%PS8-PROCESSES-J1-P2-PROCESSNAME"]/@VALUE else ""' \
  -n ~testhwa/extract.BCBR.job.xml >> /tmp/prcsname_2

内容的提问来源于stack exchange,提问作者sriram2207

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.11 21:18:02