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

使用jq与xmlstarlet转JSON为XML失败及JUnit格式需求问题

问题场景

尝试用以下jq+xmlstarlet命令将OWASP ZAP生成的JSON(含站点及告警信息)转成XML:

jq -r 'def walk(f): . as $in | if type == "object" then reduce keys_unsorted[] as $key (.; .[$key] = ($in[$key] | walk(f))) | f else f end; walk(tostring) | gsub("&"; "&")' input.json | xmlstarlet fo --omit-decl --indent-tab > output.xml

执行后报错:

-:1.1: Start tag expected, '<' not found
{"@programName":"OWASP ZAP","@version":"D-2023-05-30","@generated":"Wed, 31 May
^

已确认JSON有效,且实际需要转换为指定JUnit格式XML,之前用json_to_xml.jq生成的XML不符合需求。


错误原因

原命令的核心问题是:jq输出的仍是JSON格式字符串(仅将所有值转为字符串),并非合法XML结构。而xmlstarlet fo是用于格式化已有XML的工具,无法将JSON直接转换为XML,因此会报“缺少起始标签”的错误。


解决方案:用jq直接生成JUnit格式XML

既然目标是生成指定的JUnit XML,直接用jq构建对应XML标签结构即可,无需依赖xmlstarlet做格式转换(jq可直接输出格式化后的XML)。

示例jq脚本(适配OWASP ZAP JSON结构)

假设你的OWASP ZAP JSON包含site和alerts核心节点,以下脚本会将告警映射为JUnit的<testcase>,并将中高危告警标记为失败:

def escape_xml: gsub("&"; "&amp;") | gsub("<"; "&lt;") | gsub(">"; "&gt;") | gsub("\""; "&quot;") | gsub("'"; "&apos;");

"<testsuites>" +
(.site[] | "<testsuite name=\"\(.name | escape_xml)\" tests=\"\(.alerts | length)\" failures=\"\(.alerts[] | select(.riskcode >= 2) | length)\">" +
  (.alerts[] | "<testcase name=\"\(.alert | escape_xml)\" classname=\"\(.pluginId | escape_xml)\">" +
    (if .riskcode >= 2 then "<failure message=\"\(.riskdesc | escape_xml)\">\(.description | escape_xml)\n\(.solution | escape_xml)</failure>" else "" end) +
  "</testcase>"
  ) +
"</testsuite>"
) +
"</testsuites>"

使用方式

将上述脚本保存为zap_to_junit.jq,执行命令:

jq -rf zap_to_junit.jq input.json > output.xml

自定义调整

如果你的JUnit格式有特殊要求,可直接修改jq脚本:

  • 调整<testsuite>的属性,添加timestamp、skipped等字段
  • 修改<testcase>结构,比如增加time属性(若ZAP提供耗时数据)
  • 调整风险等级判断逻辑,例如将低危告警也标记为失败

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 11:52:07