Apache Xerces-C++ 常用 CLI 命令与工具详解
实测 Xerces-C++ 3.3.0 源码自带的 16 个样例程序(SAXCount/DOMCount/DOMPrint/PParse/XInclude 等)逐参数用法与回显,并确认官方 binary 包与 apt 包的工具差异。
Apache Xerces-C++ 常用 CLI 命令与工具详解
目标:把 Xerces-C++ 3.3.0 源码自带的 16 个样例程序当作命令行工具逐个实测——帮助信息、参数含义、真实运行回显与退出码全部转录,让读者拿到一份「装完源码就能用」的 XML 命令行工具清单。官方 Linux binary 包与 apt 包的工具差异也一并实测说明。
一、环境信息
- 操作系统:Ubuntu 22.04(x86_64)
- Xerces-C++ 3.3.0:源码 CMake 编译安装(前缀
/usr/local),16 个样例随make install落到/usr/local/bin,编译过程见《Apache Xerces-C++ 在 Ubuntu 22.04 集成使用指南》 - 样例数据目录:
/root/xerces-c-3.3.0/samples/data/(含 personal.xml、personal.dtd、personal.xsd、personal-schema.xml、redirect.dtd、long.xml) - 本文示例统一在该数据目录执行,并把
/usr/local/bin加入 PATH
💡 技术拓展:Xerces-C++ 官方仓库的样例(samples/)不只是教学代码——它们编译后就是一批实用的 XML 命令行小工具(计数、打印、校验、XInclude 展开、Schema 组件检视),功能上可以类比 xmllint 的子集。理解每个工具对应的 API 入口(SAX1/SAX2/DOMLS/渐进扫描)也是学习库设计的捷径。
二、前置条件:工具从哪来
cd /root/xerces-c-3.3.0/build
ls samples/src/ # 16 个样例源码目录
find samples -type f -executable | wc -l # 编译产物
ls -l /usr/local/bin/ | grep -cE "SAX|DOM|PParse|MemParse|StdIn|Enum|SCM|Redirect|XInclude|CreateDOM|PSVI"
实测输出:
CreateDOMDocument DOMCount DOMPrint EnumVal MemParse
PParse PSVIWriter Redirect SAX2Count SAX2Print
SAXCount SAXPrint SCMPrint SEnumVal StdInParse XInclude
16
一次 make && make install 即得全部 16 个工具,无需单独安装。样例数据随源码包分发,注意数据目录不在安装清单里,保留源码目录或自行拷贝即可。
三、命令总览
实测归纳的 16 个工具按用途分四组:
| 分组 | 工具 | 解析 API | 一句话用途 |
|---|---|---|---|
| 计数/校验 | SAXCount | SAX1 | 数元素/属性/空白/字符,可选校验 |
| 计数/校验 | SAX2Count | SAX2 | 同上,SAX2 版,参数开关方向有坑(见 4.2) |
| 计数/校验 | DOMCount | DOMLS | 建树后数元素,可打印元素名 |
| 输出打印 | SAXPrint | SAX1 | 把 SAX 事件流重排为标准 XML |
| 输出打印 | SAX2Print | SAX2 | SAX2 版,支持展开命名空间 URI |
| 输出打印 | DOMPrint | DOM | DOM 树序列化输出,支持 XPath 过滤、格式化 |
| 流式/渐进 | PParse | 渐进扫描 scanFirst/scanNext | 读到目标即停,演示渐进解析 |
| 流式/渐进 | MemParse | SAX | 直接解析内存缓冲(内置 DTD 演示) |
| 流式/渐进 | StdInParse | SAX | 从标准输入流式读取 |
| 生成/转换 | CreateDOMDocument | DOM | 内存生成一棵 4 元素文档树 |
| 生成/转换 | XInclude | DOM + XInclude | 展开 xi:include 并生成 xml:base |
| 生成/转换 | Redirect | SAX + EntityResolver | 把实体引用重定向到备用位置 |
| Schema 检视 | EnumVal | SAX1 + DTD | 枚举 DTD 里的元素与属性 |
| Schema 检视 | SEnumVal | Schema Grammar | 枚举 XSD 元素信息(入参是实例文档) |
| Schema 检视 | SCMPrint | Schema Content Model | 打印 XSD 内容模型组件 |
| Schema 检视 | PSVIWriter | SAX2 + PSVI | 输出后校验信息集(PSVI)XML 报告 |
通用约定(全部实测确认):-? 打印帮助并以退出码 2 结束(MemParse/StdInParse/SCMPrint 等少数工具退出码为 0);-v=xxx 取值 always | never | auto(带 * 号者为默认);与 head 管道组合查看长输出时,被截断侧退出码为 141(SIGPIPE,正常管道行为)。
四、计数与校验工具
4.1 SAXCount(SAX1 计数器)
完整帮助(SAXCount -? 实测):
Usage:
SAXCount [options] <XML file | List file>
This program invokes the SAX Parser, and then prints the
number of elements, attributes, spaces and characters found
in each XML file, using SAX API.
Options:
-l Indicate the input file is a List File that has a list of xml files.
Default to off (Input file is an XML file).
-v=xxx Validation scheme [always | never | auto*].
-n Enable namespace processing. Defaults to off.
-s Enable schema processing. Defaults to off.
-f Enable full schema constraint checking. Defaults to off.
-locale=ll_CC specify the locale, default: en_US.
-? Show this help.
基础用法与校验参数实测(数据目录 /root/xerces-c-3.3.0/samples/data):
SAXCount personal.xml
SAXCount -v=always personal.xml # personal.xml 带 DOCTYPE personal.dtd,可 DTD 校验
SAXCount -n -s -f personal-schema.xml # 开命名空间 + Schema + 全量约束
personal.xml: 0 ms (37 elems, 12 attrs, 134 spaces, 134 chars)
personal.xml: 1 ms (37 elems, 12 attrs, 134 spaces, 134 chars)
personal-schema.xml: 4 ms (37 elems, 29 attrs, 140 spaces, 128 chars)
三个统计口径实测确认:elems 数元素开标签、attrs 数属性、spaces/chars 分别数空白与字符数据。第三行 attrs 从 12 变 29,是因为 personal-schema.xml 的 XSD 校验路径为 id 类型等属性补充了默认声明——同一计数器在校验开/关下数字不同,这正是 -f 全量约束检查的效果。
格式不良文档与列表文件实测:
SAXCount bad1.xml # <body> 未闭合
printf "%s\n" personal.xml personal-schema.xml > /tmp/list.txt
SAXCount -l /tmp/list.txt # -l 支持列表文件批量处理
Fatal Error at file /root/xerces-c-3.3.0/samples/data/bad1.xml, line 6, char 3
Message: expected end of tag 'body'
exit=4
==Parsing== personal.xml
==Parsing== personal-schema.xml
personal.xml: 0 ms (37 elems, 12 attrs, 134 spaces, 134 chars)
personal-schema.xml: 0 ms (37 elems, 23 attrs, 0 spaces, 268 chars)
格式错误报出精确行列并以退出码 4 结束;-l 列表文件逐个打印解析统计,适合批处理目录下全部 XML。
4.2 SAX2Count(SAX2 计数器,参数方向有坑)
完整帮助里藏着三个反直觉开关(SAX2Count -? 实测原文):
Options:
-l Indicate the input file is a List File that has a list of xml files.
Default to off (Input file is an XML file).
-v=xxx Validation scheme [always | never | auto*].
-f Enable full schema constraint checking processing. Defaults to off.
-p Enable namespace-prefixes feature. Defaults to off.
-n Disable namespace processing. Defaults to on.
NOTE: THIS IS OPPOSITE FROM OTHER SAMPLES.
-s Disable schema processing. Defaults to on.
NOTE: THIS IS OPPOSITE FROM OTHER SAMPLES.
-i Disable identity constraint checking. Defaults to on.
NOTE: THIS IS OPPOSITE FROM OTHER SAMPLES.
SAX2Count/SAX2Print 的 -n、-s、-i 是「关闭」开关且默认开启,与其他样例方向相反(帮助原文自带 NOTE 提醒),批处理脚本混用时极易踩坑。基础与组合实测:
SAX2Count personal.xml
SAX2Count -p -n personal-schema.xml # -p 开前缀特性,-n 关命名空间处理
personal.xml: 0 ms (37 elems, 12 attrs, 134 spaces, 134 chars)
personal-schema.xml: 1 ms (37 elems, 23 attrs, 0 spaces, 268 chars)
第二行 spaces 从 134 变 0、attrs 12→23:关闭命名空间处理后 SAX2 走合并名路径,统计口径随之变化。两行对比就是「SAX2 与 SAX1 处理差异」的直观教材。
4.3 DOMCount(DOM 建树计数)
Usage:
DOMCount [options] <XML file | List file>
This program invokes the DOMLSParser, builds the DOM tree,
and then prints the number of elements found in each XML file.
Options:
-l Indicate the input file is a List File that has a list of xml files.
Default to off (Input file is an XML file).
-v=xxx Validation scheme [always | never | auto*].
-n Enable namespace processing. Defaults to off.
-s Enable schema processing. Defaults to off.
-f Enable full schema constraint checking. Defaults to off.
-d Disallow DOCTYPE. Defaults to false.
-locale=ll_CC specify the locale, default: en_US.
-p Print out names of elements and attributes encountered.
DOMCount personal.xml
DOMCount -v=always -s -n personal-schema.xml
DOMCount -f -s -n personal-schema.xml
personal.xml: 0 ms (37 elems).
personal-schema.xml: 1 ms (37 elems).
personal-schema.xml: 1 ms (37 elems).
实测注意:DOMCount 只数元素(不打属性/字符数);-d 参数允许拒绝带 DOCTYPE 的文档(默认允许);三种校验组合下元素计数一致——校验不改变文档结构,只影响报错。
五、输出打印工具
5.1 SAXPrint(SAX 事件流重排)
Usage:
SAXPrint [options] <XML file>
Options:
-u=xxx Handle unrepresentable chars [fail | rep | ref*].
-v=xxx Validation scheme [always | never | auto*].
-n Enable namespace processing.
-s Enable schema processing.
-f Enable full schema constraint checking.
-x=XXX Use a particular encoding for output (LATIN1*).
The parser has intrinsic support for the following encodings:
UTF-8, US-ASCII, ISO8859-1, UTF-16[BL]E, UCS-4[BL]E,
WINDOWS-1252, IBM1140, IBM037, IBM1047.
-u 取值含义(fail 遇不可表示字符即失败 / rep 替换 / ref 转成字符引用,默认 ref)。实测先给一个错误示范(-u=no 不是合法取值):
SAXPrint -u=no personal.xml
Unknown -u= value: no
exit=2
SAXPrint -u=ref -x=UTF-8 personal.xml | head -8
SAXPrint -v=always personal.xml > /tmp/saxprint.out 2>&1; echo "exit=$?"; wc -l /tmp/saxprint.out; tail -4 /tmp/saxprint.out
<?xml version="1.0" encoding="UTF-8"?>
<personnel>
<person id="Big.Boss">
<name><family>Boss</family> <given>Big</given></name>
<email>chief@foo.com</email>
<link subordinates="one.worker two.worker three.worker four.worker five.worker"></link>
exit=0
39 /tmp/saxprint.out
<link manager="Big.Boss"></link>
</person>
</personnel>
两个实测细节:非法 -u 值立即报错退出 2(参数检查是硬校验);-x=UTF-8 把输出从默认 LATIN1 换成 UTF-8(首行 encoding 声明同步变化),全文档 39 行。注意 SAXPrint 的输出是「事件流重排」——空元素会被写成 <link ...></link> 起止对形式(上例可见),与源文档的自闭合写法不同,属预期行为而非缺陷。
5.2 SAX2Print(SAX2 版打印)
SAX2Print 帮助同样带 -n/-s 方向相反的 NOTE(同 4.2,不再重复),另有三个独有参数:-e 展开命名空间别名为完整 URI、-p 启用前缀特性、-sa 属性按字母序打印。展开效果实测(对比强烈,输出节选):
SAX2Print -e -p -x=UTF-8 personal-schema.xml | head -12
<?xml version="1.0" encoding="UTF-8"?>
<?proc-inst-1 'foo' ?><personnel http://www.w3.org/2000/xmlns/:xsi="http://www.w3.org/2001/XMLSchema-instance" http://www.w3.org/2001/XMLSchema-instance:noNamespaceSchemaLocation="personal.xsd">
<person id="Big.Boss" contr="false">
<name http://www.w3.org/XML/1998/namespace:base="foo/bar">...
-e 后属性名全部展开为完整 URI 形态,直观展示了命名空间的「名字=URI 对」本质,排查命名空间冲突时非常好用。
5.3 DOMPrint(DOM 序列化 + XPath 过滤)
DOMPrint 帮助最长(实测 90+ 行),参数与前两者不同:输出编码用 -wenc= 而非 -x=,格式化用 -wfpp=,还有 -xpath 过滤、-u= 同款取值等。实测先给一个参数混用示范(SAXPrint 习惯带过来的 -x= 会被忽略并警告):
DOMPrint -wfpp=on -x=UTF-8 personal.xml | head -5 # -x 不是 DOMPrint 的参数
DOMPrint -wenc=UTF-8 -wfpp=on personal.xml | head -5 # 正确姿势
DOMPrint -xpath=//email personal.xml
Unknown option '-x=UTF-8', ignoring it.
<?xml version="1.0" encoding="iso-8859-1" standalone="no" ?>
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<!DOCTYPE personnel SYSTEM "personal.dtd">
<!-- @version: -->
<personnel>
<email>chief@foo.com</email><email>one@foo.com</email><email>two@foo.com</email><email>three@foo.com</email><email>four@foo.com</email><email>five@foo.com</email>
实测要点:-x=UTF-8 只打警告并忽略(比 SAXPrint 的硬报错宽松,但 encoding 声明仍是 iso-8859-1——必须用 -wenc=UTF-8 才真正改输出编码);-wfpp=on 开启 pretty-print(DOM 树按源文档缩进排版);-xpath=//email 精准抽取 6 个 email 元素,是临时查数据的利器。
六、流式与渐进工具
6.1 PParse(渐进解析:读到即停)
Usage:
PParse [options] <XML file>
This program demonstrates the progressive parse capabilities of
the parser system. It allows you to do a scanFirst() call followed by
a loop which calls scanNext(). You can drop out when you've found what
ever it is you want. In our little test, our event handler looks for
16 new elements then sets a flag to indicate its found what it wants.
At that point, our progressive parse loop exits.
Options:
-v=xxx - Validation scheme [always | never | auto*].
-n - Enable namespace processing [default is off].
-s - Enable schema processing [default is off].
-f - Enable full schema constraint checking [default is off].
实测校验组合的两种结局(long.xml 是一个 SOAP 信封大文件,无 DTD/XSD):
PParse -v=always -n long.xml # 强校验但文档无语法 → 报错退出
PParse -v=never long.xml # 不校验 → 正常
Error at file .../long.xml, line 1, char 291
Message: no declaration found for element 'soap:Envelope'
...(每个 xmlns 声明一条)
exit=4
long.xml: 1 ms (4 elems, 7 attrs, 0 spaces, 5 chars)
exit=0
第一段再次印证《Apache Xerces-C++ 3.3.0 配置参数详解》的结论:validation=true 而文档无语法引用时会产生 no-declaration 报错群。第二段正常完成——注意结果 4 elems,这是样例逻辑在第 16 个元素满足后主动退出的设计(帮助文本说明),并不代表 long.xml 只有 4 个元素。
6.2 MemParse(内存缓冲解析)
Usage:
MemParse [options]
This program uses the SAX Parser to parse a memory buffer
containing XML statements, and reports the number of
elements and attributes found.
无文件参数,解析程序内置的带内联 DTD 的缓冲(company/product/... 文档),实测输出:
Finished parsing the memory buffer containing the following XML statements:
...(回显内置 XML 全文)
Parsing took 0 ms (4 elements, 1 attributes, 16 spaces, 95 characters).
exit=0
它同时演示了「内联 DTD 校验」:缓冲里内嵌 <!ELEMENT>/<!ATTLIST> 声明,-v=always 下即校验通过。适合验证解析器本体安装是否健康。
6.3 StdInParse(标准输入流式解析)
Usage:
StdInParse [options] < <XML file>
Options:
-v=xxx Validation scheme [always | never | auto*].
-n Enable namespace processing. Defaults to off.
管道场景实测:
cat personal.xml | StdInParse -v=never
stdin: 0 ms (37 elems, 12 attrs, 0 spaces, 268 chars)
exit=0
stdin 场景 spaces=0(流式读入没有源文件上下文),其余统计与 SAXCount 一致。做「curl 拉远程 XML 立即解析」的组合时用它最顺手。
七、生成与转换工具
7.1 CreateDOMDocument(内存建树)
CreateDOMDocument
The tree just created contains: 4 elements.
exit=0
演示 DOM API 从零创建文档树(不落盘)。写 XML 生成器时可以直接拿它的源码当骨架。
7.2 XInclude(XI:Include 展开)
Usage:
XInclude [-h] InputFile OutputFile
-h : Prints this help message and exits.
样例数据不含 XInclude 输入,自备一对文件实测(xi:include 引用 section 内容):
cat > inc-main.xml <<'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<main xmlns:xi="http://www.w3.org/2001/XInclude">
<title>XInclude demo</title>
<xi:include href="inc-part.xml"/>
</main>
EOF
cat > inc-part.xml <<'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<section>Included content goes here.</section>
EOF
XInclude inc-main.xml inc-out.xml
cat inc-out.xml
Parse inc-main.xml in progress ... finished.
Writing result to: inc-out.xml
<?xml version="1.0" encoding="UTF-8" standalone="no" ?><main xmlns="" xmlns:xi="http://www.w3.org/2001/XInclude">
<title>XInclude demo</title>
<section xml:base="inc-part.xml">Included content goes here.</section>
</main>
实测确认展开完整:xi:include 被替换为目标文档内容,并自动补写 xml:base="inc-part.xml" 记录来源;输出还带上了 xmlns="" 空命名空间声明(XInclude 处理器的标准化行为)。嵌套 include 同样支持(深度由解析器处理)。
7.3 Redirect(实体解析重定向)
Redirect personal.xml
personal.xml: 1 ms (37 elems, 12 attrs, 0 spaces, 268 chars)
exit=0
该样例实现 EntityResolver,把 DTD 引用重定向到备用路径解析(数据目录中的 redirect.dtd 即为其备件),是「解析不联网也能找到本地 DTD」的标准参考实现——生产上把这一套逻辑抄进自己的 EntityResolver 即可实现 DTD 离线化。
八、Schema 检视工具
8.1 EnumVal 与 SEnumVal(元素枚举,入参类型不同)
两个工具实测踩点(如实记录错误用法):
EnumVal personal.xsd # 错误:EnumVal 走 DTD,不吃 XSD
EnumVal personal.xml # 正确:从 DOCTYPE 取 DTD 枚举
SEnumVal personal.xsd # 错误:SEnumVal 不收 schema 文件
SEnumVal employee.xml # 正确:收带 xsi 引用的实例文档
$ EnumVal personal.xsd
The validator has no elements to display
$ EnumVal personal.xml | head -12
ELEMENTS:
----------------------------
Name: personnel
Content Model: (person)+
Name: person
Content Model: (name,email*,url*,link?)
Attributes:
Name:id, Type: ID
Name: name
$ SEnumVal personal.xsd
Errors occurred, no output available
$ SEnumVal employee.xml | head -18
Name: employee
Model Type: Children
Create Reason: Declared
ContentType: Sequence
Content Model: (name,age)
ComplexType:
TypeName: ,__AnonC0
ContentType: Sequence
Attributes:
Name: id
Type: CDATA
Default Type: #REQUIRED
Base Datatype: string
--------------------------------------------
Name: name
Model Type: Simple
Create Reason: Declared
实测结论:EnumVal 枚举 DTD 声明(入参是实例文档,读其 DOCTYPE),输出元素内容模型与属性表(含 ID/CDATA 等类型);SEnumVal 枚举 XSD 元素信息(入参同样是实例文档,读其 xsi 引用的 schema),输出内容模型、复杂类型名、属性的数据类型(Base Datatype: string 等),直接喂 XSD 文件会得到 "no elements to display" 或 "Errors occurred"——与直觉相反,值得单独记一笔。
8.2 SCMPrint(内容模型打印)
Usage:
SCMPrint [options] <XSD file | List file>
Options:
-f Enable full schema constraint checking processing. Defaults to off.
-l Indicate the input file is a List File that has a list of XSD files.
与 EnumVal/SEnumVal 不同,SCMPrint 的入参就是 XSD 文件本身:
SCMPrint -f personal.xsd | head -12
********** Printing out information from Schema **********
Processing Namespace:
============================================
Name: personnel
Component Type: Element
Content Model
Type: Complex
Name: __AnonC0
按命名空间逐个打印全局组件(元素/复杂类型),排查 XSD 结构时比肉眼读文件高效。
8.3 PSVIWriter(PSVI 信息集输出)
Usage:
PSVIWriter [options] <XML file | List file>
Options:
-f Enable full schema constraint checking processing. Defaults to off.
-o=xxx Output PSVI to file xxx (default is stdout)
-e=xxx Output errors to file xxx (default is stdout)
-u=xxx Handle unrepresentable chars [fail | rep | ref*].
PSVIWriter personal-schema.xml | head -5
<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:psv="http://apache.org/xml/2001/PSVInfosetExtension" xmlns="http://www.w3.org/2001/05/XMLInfoset">
<characterEncodingScheme>UTF-8</characterEncodingScheme>
<standalone xsi:nil="true"/>
<version>1.0</version>
<children>
<processingInstruction>
💡 技术拓展:PSVI(Post-Schema-Validation Infoset,后校验信息集)是 XSD 校验完成后附在信息集上的增值数据——每个元素的实际类型、取值域、校验结果等。PSVIWriter 把它转成 XML 报告,是研究「校验器到底知道了什么」最直观的窗口,调试 Schema 派生/类型替换问题时常能救命。
九、官方 binary 包与 apt 包对照
官方 binary 包:实测访问 https://downloads.apache.org/xerces/c/3/binaries/ 目录为空(仅剩上级目录链接),即 3.x 当前不发布官方 Linux 二进制包,3.3.0 仅源码分发;Windows 平台的旧版二进制可在 archive.apache.org 历史库中找到。结论:Linux 上的工具获取路径就是「源码编译」(见《Apache Xerces-C++ 在 Ubuntu 22.04 集成使用指南》)。
apt 包:Ubuntu 22.04 的 libxerces-c-dev(3.2.3+debian)只含库、头文件与静态库,不带这 16 个样例工具(dpkg -L libxerces-c-dev 实测无 bin 下可执行文件)。需要本文工具集必须走源码编译路线;另 Debian 系发行版把 libxml2 的 xmllint 等工具装成独立包,Xerces-C++ 无对应发行版工具包,这与其「仅源码分发」的官方策略一致。
十、常见问题
Q1:SAXCount -? 打印帮助后退出码是 2,脚本里怎么判断?
样例把「无文件参数/仅 -?」都当参数错误处理,退出码 2;成功解析 0;解析错误 4。脚本判断用退出码时注意区分。
Q2:| head 查看输出时退出码 141?
SIGPIPE 管道信号,head 截断输出所致,非工具故障。需要完整退出码时把输出重定向到文件(如 5.1 的 /tmp/saxprint.out 用法)。
Q3:SAX2Count/SAX2Print 的 -n/-s 行为和 SAXCount 相反?
是样例自带的历史设计,帮助文本里 NOTE: THIS IS OPPOSITE FROM OTHER SAMPLES 明示。SAX2 系列这三个开关是「关闭」语义且默认开启,写脚本时逐条对照帮助确认。
Q4:SEnumVal 报 "Errors occurred, no output available"? 入参给错成 XSD 文件了。SEnumVal 要吃带 xsi:schemaLocation / xsi:noNamespaceSchemaLocation 引用的实例文档(8.1 实测);直接打印 XSD 组件请用 SCMPrint。
Q5:哪里看完整参数?
每个工具 -? 都有完整帮助;DOMPrint 的帮助最长(90+ 行,含 -wenc/-wfpp/-xpath 等),建议按需 -? 现查,不要凭记忆混用其他工具的参数。
十一、参考链接
- 官方样例源码(与本文实测一一对应):https://xerces.apache.org/xerces-c/
- 官方样例说明页:https://xerces.apache.org/xerces-c/samples-3.html
- XInclude 1.0 规范:https://www.w3.org/TR/xinclude/
- 本文配套篇:《Apache Xerces-C++ 在 Ubuntu 22.04 集成使用指南》《Apache Xerces-C++ 3.3.0 配置参数详解》《Apache Xerces-C++ 介绍与选型指南》