Apache Daffodil 常用 CLI 命令与工具详解
Apache Daffodil 4.2.0 命令行工具详解,介绍 daffodil 全局选项与 parse、unparse、save-parser、test、performance、generate、exi 等子命令的语法、参数与真实回显。
Apache Daffodil 常用 CLI 命令与工具详解
本文基于 Apache Daffodil 4.2.0 实测,梳理
bin/daffodil的全局选项与全部常用子命令,给出语法、关键参数、典型用法与真实回显。
一、CLI 概览与全局选项
daffodil 采用「全局选项 + 子命令 + 子命令选项」结构:
daffodil [GLOBAL_OPTS] <subcommand> [SUBCOMMAND_OPTS]
真实回显(daffodil --help):
Usage: daffodil [GLOBAL_OPTS] <subcommand> [SUBCOMMAND_OPTS]
Global Options:
-v, --verbose Increment verbosity level, one level for each -v
-h, --help Show help message
--version Show Daffodil's version
Subcommands:
parse Parse data to a DFDL infoset
unparse Unparse a DFDL infoset
save-parser Save a Daffodil parser for reuse
test List or execute TDML tests
performance Run performance test
generate Generate <language> code from a DFDL schema
exi Encode an XML file with EXI
Run 'daffodil <subcommand> --help' for subcommand specific options
| 全局选项 | 含义 |
|---|---|
-v, --verbose | 逐级提高日志详细度,可叠加(-vv) |
-h, --help | 显示帮助 |
--version | 显示版本 |
daffodil --version
真实回显:
Apache Daffodil 4.2.0
二、parse 子命令
2.1 语法与参数
Usage: daffodil parse (-s <schema> | -P <parser>) [PARSE_OPTS] [--] [infile]
数据来源二选一:-s <schema>(DFDL schema 文件)或 -P <parser>(已保存的解析器文件)。常见选项:
| 选项 | 含义 |
|---|---|
-s, --schema <file> | 使用 DFDL schema 创建解析器 |
-P, --parser <file> | 复用 save-parser 保存的解析器 |
-r, --root <node> | 指定根元素(可带 {namespace} 前缀),仅配合 -s |
-I, --infoset-type <type> | 信息集输出类型:xml(默认)、json、exi、jdom、w3cdom、sax、scala-xml、null |
-o, --output <file> | 输出文件,缺省或 - 表示写到标准输出 |
-c, --config <file> | XML 配置文件(tunables / 外部变量) |
-D var=value | 指定外部变量,可带 {namespace} 前缀 |
-T tunable=value | 指定 tunable,可多个 |
-V, --validate <name> | 校验器:off、daffodil、xerces[=value]、schematron[=value] |
-t, --trace | 输出详细 trace(不可与 --debug 同用) |
-d, --debug [file] | 交互式调试器 |
--stream / --nostream | 剩余数据是否继续按 NUL 分隔多次解析 |
2.2 典型用法
解析为 XML 信息集:
daffodil parse -s person.dfdl.xsd person.txt
真实回显:
<?xml version="1.0" encoding="UTF-8"?>
<tns:person xmlns:tns="http://example.com/dfdl/person">
<name>Alice</name>
<age>25</age>
<code>AB</code>
</tns:person>
解析为 JSON 信息集并落盘:
daffodil parse -s person.dfdl.xsd -I json person.txt -o person.json
真实回显(-I json 到标准输出):
{
"person": {
"name": "Alice",
"age": 25,
"code": "AB"
}
}
启用校验器:
daffodil parse -s person.dfdl.xsd -V daffodil person.txt
trace 追踪(节选):
parser: <Element name='person'><Sequence>.........</Sequence></Element>
bitPosition: 0
data:
? ?
87654321 0011 2233 4455 6677 8899 aabb ccdd eeff 0123456789abcdef
00000000: 416c 6963 6530 3235 4142 Alice025AB
infoset:
<tns:person></tns:person>
diff:
(no differences)
从标准输入读取:
cat person.txt | daffodil parse -s person.dfdl.xsd -
三、unparse 子命令
3.1 语法与参数
Usage: daffodil unparse (-s <schema> | -P <parser>) [--] [infile]
选项与 parse 基本一致,另有:
| 选项 | 含义 |
|---|---|
-o, --output <file> | 原始数据输出文件,缺省或 - 表示标准输出 |
--stream | 输入按 NUL 分隔,逐块回写 |
--nostream | 整个输入视为一个信息集 |
unparse当前不支持校验(帮助中注明 “using this flag doesn't use the created validator as unparse validation is currently unsupported”)。
3.2 典型用法(与 parse 组成闭环)
daffodil parse -s person.dfdl.xsd person.txt -o person.xml
daffodil unparse -s person.dfdl.xsd person.xml -o person.out
od -c person.out
cmp person.txt person.out && echo IDENTICAL
真实回显:
0000000 A l i c e 0 2 5 A B
0000012
IDENTICAL
输出与原始数据字节级一致。
四、save-parser 子命令
4.1 语法
Usage: daffodil save-parser -s <schema> [SAVE_PARSER_OPTIONS] [--] [outfile]
把编译好的解析器序列化保存,后续 parse/unparse 用 -P 复用,省去重复编译开销。支持 -c、-D、-r、-T。
4.2 典型用法
daffodil save-parser -s person.dfdl.xsd person.parser.bin
ls -l person.parser.bin
daffodil parse -P person.parser.bin person.txt
真实回显:
-rw-r--r-- 1 root root 11924 ... person.parser.bin
# daffodil parse -P person.parser.bin person.txt 输出与 parse 一致
五、test 子命令
5.1 语法
Usage: daffodil test [TEST_OPTIONS] [--] <tdmlfile> [testnames...]
用于执行 TDML(Test Data Markup Language)测试套件。选项:
| 选项 | 含义 |
|---|---|
-l, --list | 仅列出测试名,不执行 |
-r, --regex | 把 <testnames...> 当作正则 |
-I, --implementation <impl> | 实现:daffodil(默认)、daffodilC、ibm |
-i, --info | 逐级增加结果信息输出 |
-t, --trace / -d, --debug | trace / 调试 |
5.2 TDML 文件要点
defineSchema 内直接放置 schema 组件(xs:include、dfdl:format、xs:element、xs:complexType 等),不要包 <xs:schema>。defineSchema 生成的内联 schema 目标命名空间为 http://example.com:
<tdml:testSuite xmlns:tdml="http://www.ibm.com/xmlns/dfdl/testData"
xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:ex="http://example.com"
suiteName="PersonTestSuite">
<tdml:defineSchema name="personSchema" elementFormDefault="unqualified">
<xs:include schemaLocation="/org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
<dfdl:format ref="ex:GeneralFormat" encoding="ASCII" representation="text"/>
<xs:element name="person" type="ex:PersonType" dfdl:lengthKind="implicit"/>
<xs:complexType name="PersonType">
<xs:sequence>
<xs:element name="name" type="xs:string"
dfdl:lengthKind="explicit" dfdl:length="5" dfdl:lengthUnits="characters"/>
<xs:element name="age" type="xs:unsignedInt"
dfdl:lengthKind="explicit" dfdl:length="3" dfdl:lengthUnits="characters"
dfdl:textNumberPattern="000"/>
<xs:element name="code" type="xs:string"
dfdl:lengthKind="explicit" dfdl:length="2" dfdl:lengthUnits="characters"/>
</xs:sequence>
</xs:complexType>
</tdml:defineSchema>
<tdml:parserTestCase name="person_parse_01" model="personSchema" roundTrip="true">
<tdml:document><tdml:documentPart type="text">Alice025AB</tdml:documentPart></tdml:document>
<tdml:infoset>
<tdml:dfdlInfoset>
<person xmlns="http://example.com">
<name>Alice</name><age>25</age><code>AB</code>
</person>
</tdml:dfdlInfoset>
</tdml:infoset>
</tdml:parserTestCase>
</tdml:testSuite>
5.3 运行
daffodil test -l person.tdml
daffodil test person.tdml
真实回显:
# -l
person_parse_01
# 运行
[Pass] person_parse_01
Total: 1, Pass: 1, Fail: 0, Not Found: 0
roundTrip="true" 会同时执行 parse 与 unparse 并比对字节,相当于一次闭环校验。
六、performance 子命令
6.1 语法
Usage: daffodil performance (-s <schema> | -P <parser>) [PERFORMANCE_OPTIONS] [--] <infile>
用于吞吐/耗时压测,关键选项:
| 选项 | 含义 |
|---|---|
-N, --number <n> | 处理文件总数,默认 1 |
-t, --threads <n> | 线程数,默认 1 |
-u, --unparse | 改为测试 unparse |
-I, --infoset-type <type> | 信息集输出类型 |
6.2 典型用法
daffodil performance -s person.dfdl.xsd -N 100000 -t 4 person.txt
该命令对同一输入重复解析 10 万次以统计吞吐,适合评估 schema 性能。
七、generate 与 exi 子命令
7.1 generate
从 DFDL schema 生成代码(当前支持 C):
Usage: daffodil [GLOBAL_OPTS] generate <language> [SUBCOMMAND_OPTS]
Subcommands:
c Generate C code from a DFDL schema
daffodil generate c -s person.dfdl.xsd -o out/
7.2 exi
对 XML 做 EXI(Efficient XML Interchange)编码:
daffodil exi --help
八、公共选项与退出码
8.1 常用选项速查
| 选项 | 适用子命令 | 说明 |
|---|---|---|
-s/--schema | parse / unparse / save-parser / performance | DFDL schema 文件 |
-P/--parser | parse / unparse / performance | 复用已保存解析器 |
-o/--output | parse / unparse | 输出文件 |
-I/--infoset-type | parse / unparse / performance | 信息集类型(xml/json/…) |
-r/--root | parse / unparse / save-parser / performance | 根元素 |
-c/--config | parse / unparse / save-parser / performance | XML 配置文件 |
-D | parse / unparse / save-parser / performance | 外部变量 |
-T | parse / unparse / save-parser / performance | tunable |
-V/--validate | parse / performance | 校验器 |
-t/--trace、-d/--debug | parse / unparse / test | trace / 调试 |
8.2 退出码
实测常见退出码:
| 退出码 | 含义 | 触发示例 |
|---|---|---|
| 0 | 成功 | 正常 parse/unparse |
| 20 | 处理错误 | 数据与 schema 不匹配 |
| 24 | 测试失败 | daffodil test 存在 Fail |
| 35 | Schema 定义错误 | schema 缺少必需格式属性 |
| 64 | 命令行用法错误 | 选项冲突(如同时给 -s 与错误的 --parser) |
8.3 错误回显示例
数据不足时的解析错误:
[error] Parse Error: Unable to parse xs:unsignedInt from text: 25A
Schema context: age Location line 24 column 8 in person.dfdl.xsd
Data location was preceding byte 8 limit(bytes) 8
九、综合示例:一条命令链完成解析、回写与校验
cd /root/dfdl
# 1) 保存解析器
daffodil save-parser -s person.dfdl.xsd person.parser.bin
# 2) 用解析器解析为 XML
daffodil parse -P person.parser.bin person.txt -o person.xml
# 3) 回写为原始数据
daffodil unparse -P person.parser.bin person.xml -o person.out
# 4) 比对
cmp person.txt person.out && echo IDENTICAL
# 5) 运行 TDML 测试
daffodil test person.tdml
真实回显:
IDENTICAL
[Pass] person_parse_01
Total: 1, Pass: 1, Fail: 0, Not Found: 0