Apache Daffodil 常用 CLI 命令与工具详解

Apache Daffodil 4.2.0 命令行工具详解,介绍 daffodil 全局选项与 parse、unparse、save-parser、test、performance、generate、exi 等子命令的语法、参数与真实回显。

Apache DaffodilApache Daffodil2026/10/11

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, --debugtrace / 调试

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/--schemaparse / unparse / save-parser / performanceDFDL schema 文件
-P/--parserparse / unparse / performance复用已保存解析器
-o/--outputparse / unparse输出文件
-I/--infoset-typeparse / unparse / performance信息集类型(xml/json/…)
-r/--rootparse / unparse / save-parser / performance根元素
-c/--configparse / unparse / save-parser / performanceXML 配置文件
-Dparse / unparse / save-parser / performance外部变量
-Tparse / unparse / save-parser / performancetunable
-V/--validateparse / performance校验器
-t/--trace、-d/--debugparse / unparse / testtrace / 调试

8.2 退出码

实测常见退出码:

退出码含义触发示例
0成功正常 parse/unparse
20处理错误数据与 schema 不匹配
24测试失败daffodil test 存在 Fail
35Schema 定义错误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