鸿蒙新特性实战:@ohos.convertxml 打造 XML 解析实验室
前言
在移动开发中,XML(Extensible Markup Language)虽然不如 JSON 流行,但在企业级场景中仍然大量存在——SOAP 接口、RSS 订阅、配置文件、办公文档(如 OOXML 格式的 .docx/.xlsx),底层都是 XML。处理这些数据时,你当然可以手写正则或字符串解析,但那意味着你要自己处理嵌套标签、属性、注释、CDATA、实体转义等繁琐细节。
HarmonyOS NEXT 提供了 @ohos.convertxml 模块,一行 API 就能把 XML 字符串变成结构化的 JavaScript 对象,并且通过 ConvertOptions 精细控制解析行为:是否保留属性、是否忽略注释、自定义输出键名等等。
本文用一个可交互的"XML 解析实验室",把 @ohos.convertxml 讲透:切换 5 种解析选项、加载 4 种不同场景的 XML 样本、实时查看解析结果。全文含完整可运行代码,适合需要在鸿蒙应用中处理 XML 数据的中级开发者。
一、@ohos.convertxml 概述
1.1 模块定位
@ohos.convertxml 是 HarmonyOS 提供的 XML 解析工具,位于 @kit.ArkTS 工具库中。核心功能一言蔽之:将 XML 字符串转换为 JavaScript 对象。转换后的对象可以直接用 JSON.stringify 序列化,也可以通过点号访问属性,极大简化了 XML 数据的读取流程。
1.2 核心 API:ConvertXML 类
从 API 14 开始,推荐通过 ConvertXML 类来调用解析功能:
import convertxml from '@ohos.convertxml';
const converter = new convertxml.ConvertXML();
const result: Object = converter.fastConvertToJSObject(xmlString, options);
其中 options 是一个 ConvertOptions 对象,它控制了两类配置:
- 行为开关(boolean):是否去除空白、是否忽略属性/注释/CDATA/指令/声明等
- 输出键名(string):自定义解析结果中各组成部分的 JSON key 名称
fastConvertToJSObject 是自 API 14 以来推荐使用的方法,之前的 convertToJSObject 和 convert 方法均已标记为 deprecated。
二、ConvertOptions 详解
ConvertOptions 接口定义了约 18 个属性,下面按用途分类讲解。
2.1 行为开关(7 个 boolean)
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
trim |
boolean |
false |
是否去除文本前后的空白字符 |
ignoreDeclaration |
boolean? |
— | 是否忽略 XML 声明(<?xml version="1.0"?>) |
ignoreInstruction |
boolean? |
— | 是否忽略处理指令(<?xxx?>) |
ignoreAttributes |
boolean? |
— | 是否忽略元素属性 |
ignoreComment |
boolean? |
— | 是否忽略 XML 注释(<!-- -->) |
ignoreCDATA |
boolean? |
— | 是否忽略 CDATA 段(<![CDATA[ ]]>) |
ignoreDoctype |
boolean? |
— | 是否忽略 DOCTYPE 声明 |
注意:只有 trim 是必填属性,其余带 ? 的都是可选属性,不传则使用默认行为。
2.2 输出键名(11 个 string)
这些属性让你自定义解析结果中的 key 名称,对于对接不同后端或适配已有代码中的字段名非常有用:
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
declarationKey |
string |
"declaration" |
声明部分的键名 |
instructionKey |
string |
"instruction" |
处理指令的键名 |
attributesKey |
string |
"attributes" |
元素属性的键名 |
textKey |
string |
"text" |
文本内容的键名 |
cdataKey |
string |
"cdata" |
CDATA 段的键名 |
doctypeKey |
string |
"doctype" |
DOCTYPE 声明的键名 |
commentKey |
string |
"comment" |
注释的键名 |
parentKey |
string |
"parent" |
父节点引用的键名 |
typeKey |
string |
"type" |
节点类型的键名 |
nameKey |
string |
"name" |
节点名称的键名 |
elementsKey |
string |
"elements" |
子元素列表的键名 |
这些键名在 ArkTS 严格模式下也全都是必填属性。实际使用中,保持默认值即可满足绝大多数场景,但了解它们的存在很重要——当你需要把解析结果直接适配某个特定 schema 时,改键名比写映射逻辑更优雅。
三、解析选项的实际效果
光看参数表可能不够直观,下面用一个真实的 XML 片段演示各选项开关后的效果。
3.1 基线:全部关闭(不 trim,不忽略任何内容)
<catalog>
<!-- 这是一个注释 -->
<product id="P001">
<name><![CDATA[iPhone 15 Pro]]></name>
<price>8999.00</price>
</product>
</catalog>
所有选项关闭,解析结果完整保留注释、属性、CDATA:
{
"type": "element",
"name": "catalog",
"elements": [
{ "type": "comment", "comment": " 这是一个注释 " },
{
"type": "element",
"name": "product",
"attributes": { "id": "P001" },
"elements": [
{
"type": "element",
"name": "name",
"elements": [{ "type": "cdata", "cdata": "iPhone 15 Pro" }]
},
{
"type": "element",
"name": "price",
"elements": [{ "type": "text", "text": "8999.00" }]
}
]
}
]
}
3.2 开启 ignoreComment
注释节点从结果中消失,输出更干净。
3.3 开启 ignoreAttributes
"attributes": { "id": "P001" } 不再出现,只保留元素名称和子节点。
3.4 开启 ignoreCDATA
CDATA 节点被忽略,原本 iPhone 15 Pro 的内容不再出现在输出中。
3.5 开启 trim
所有文本节点前后的空白被去除,处理从 HTML/XML 格式化字符串中提取数据时非常有用。
3.6 开启 ignoreInstruction
处理指令 <?xxx?> 被忽略。在 RSS 场景中,某些 feed 会携带样式表指令 <?xml-stylesheet?>,开启此选项可过滤掉。
这些选项可以组合使用——在实际开发中,根据数据源的特点精确控制解析行为,能省去大量的后处理代码。


四、实战:XML 解析实验室
4.1 整体设计
实验室页面包含以下交互区域:
- 样本选择区:4 个预设 XML 样本(书店、RSS、配置文件、简单消息),一键切换
- XML 输入区:可编辑的 TextArea,支持粘贴自定义 XML
- 解析选项区:5 个 Toggle 开关,实时切换解析参数
- 结果展示区:Scroll 容器展示格式化 JSON 输出;解析失败时显示红色错误提示
4.2 状态与导入
import { router } from '@kit.ArkUI';
import convertxml from '@ohos.convertxml';
import { FontSize, Spacing } from '../common/Constants';
注意导入方式:import convertxml from '@ohos.convertxml' 是 default import,不是从 @kit.ArkTS 的命名导出。这是因为 @ohos.convertxml 模块导出的是一个 xml 命名空间(namespace),包含 ConvertXML 类和 ConvertOptions 接口。
ConvertOptions 接口在 ArkTS 严格模式下要求定义好所有必填属性。我们的项目中独立声明了 ConvertOpts 接口,保证与 SDK 完全兼容:
interface ConvertOpts {
trim: boolean;
ignoreDeclaration: boolean;
ignoreInstruction: boolean;
ignoreAttributes: boolean;
ignoreComment: boolean;
ignoreCDATA: boolean;
ignoreDoctype: boolean;
declarationKey: string;
instructionKey: string;
attributesKey: string;
textKey: string;
cdataKey: string;
doctypeKey: string;
commentKey: string;
parentKey: string;
typeKey: string;
nameKey: string;
elementsKey: string;
}
页面核心状态:
@State xml: string = '<bookstore>...</bookstore>';
@State jsonOut: string = '';
@State errorMsg: string = '';
@State optTrim: boolean = false;
@State optIgnoreAttrs: boolean = false;
@State optIgnoreComments: boolean = false;
@State optIgnoreCDATA: boolean = false;
@State optIgnoreInstruction: boolean = true; // 默认忽略指令
4.3 核心解析逻辑
private parseXml(): void {
this.errorMsg = '';
try {
const opts: ConvertOpts = {
trim: this.optTrim,
ignoreDeclaration: true,
ignoreInstruction: this.optIgnoreInstruction,
ignoreAttributes: this.optIgnoreAttrs,
ignoreComment: this.optIgnoreComments,
ignoreCDATA: this.optIgnoreCDATA,
ignoreDoctype: true,
declarationKey: 'declaration',
instructionKey: 'instruction',
attributesKey: 'attributes',
textKey: 'text',
cdataKey: 'cdata',
doctypeKey: 'doctype',
commentKey: 'comment',
parentKey: 'parent',
typeKey: 'type',
nameKey: 'name',
elementsKey: 'elements'
};
const converter: convertxml.ConvertXML = new convertxml.ConvertXML();
const result: Object = converter.fastConvertToJSObject(this.xml, opts);
this.jsonOut = this.toJson(result);
} catch (e) {
this.errorMsg = 'XML 解析失败,请检查格式';
this.jsonOut = '';
}
}
几点说明:
- 实例化 ConvertXML:
new convertxml.ConvertXML()创建解析器实例,调用fastConvertToJSObject执行解析。这和使用静态方法的体验一致,但更符合 API 14+ 的新架构。 - try-catch 保护:XML 格式错误时,库会抛出
BusinessError(错误码 10200002),捕获后显示友好提示。 ignoreDeclaration和ignoreDoctype固定为true:实际业务中几乎不需要 XML 声明和 DOCTYPE,所以默认忽略,减少输出噪音。toJson(obj: Object): string辅助方法:调用JSON.stringify(obj, undefined, 2)输出带缩进的格式化 JSON,方便查看层级结构。
4.4 四个预设样本
private loadSample(type: string): void {
this.errorMsg = '';
if (type === 'bookstore') {
this.xml = '<bookstore>\n <book category="技术">\n <title>鸿蒙开发实战</title>\n <author>张三</author>\n <price>59.00</price>\n </book>\n <book category="文学">\n <title>江村经济</title>\n <author>费孝通</author>\n <price>38.00</price>\n </book>\n</bookstore>';
} else if (type === 'rss') {
this.xml = '<rss version="2.0">\n <channel>\n <title>鸿蒙开发者博客</title>\n <link>https://example.com</link>\n <description>最新鸿蒙开发资讯</description>\n <item>\n <title>ArkUI 声明式开发</title>\n <pubDate>2026-07-15</pubDate>\n </item>\n </channel>\n</rss>';
} else if (type === 'config') {
this.xml = '<config>\n <database>\n <host>127.0.0.1</host>\n <port>3306</port>\n <user>admin</user>\n </database>\n <!-- 缓存配置 -->\n <cache enabled="true">\n <ttl>3600</ttl>\n </cache>\n</config>';
} else {
this.xml = '<root>\n <message>Hello 鸿蒙</message>\n <count>42</count>\n</root>';
}
this.parseXml();
}
四个样本覆盖了不同的业务场景:
- bookstore:多层级嵌套 + 属性(
category),演示属性解析 - rss:标准 RSS 2.0 格式,演示实际数据格式处理
- config:带注释的配置文件,演示
ignoreComment效果 - simple:最简单的 XML,用于理解基础结构
4.5 解析选项 Toggle 控制
5 个 Toggle 开关绑定到 5 个 @State boolean,每次切换立即触发 parseXml():
private options: OptionItem[] = [
{ key: 'optTrim', label: 'trim 去除空白' },
{ key: 'optIgnoreAttrs', label: 'ignoreAttributes 忽略属性' },
{ key: 'optIgnoreComments', label: 'ignoreComment 忽略注释' },
{ key: 'optIgnoreCDATA', label: 'ignoreCDATA 忽略CDATA' },
{ key: 'optIgnoreInstruction', label: 'ignoreInstruction 忽略指令' }
];
在 UI 中使用 ForEach 渲染,每个 Toggle 通过 getOptValue / setOptValue 读写对应的 @State 变量:
Toggle({ type: ToggleType.Switch, isOn: this.getOptValue(opt.key) })
.selectedColor('#7C3AED')
.onChange((v: boolean) => {
this.setOptValue(opt.key, v);
this.onOptionChange();
})
getOptValue / setOptValue 通过 if/else 分支映射 key 到具体 @State 变量——在 ArkTS 严格模式下,不能用动态属性名访问 this[key],显式分支是最稳妥的做法。
4.6 结果展示
解析成功时,输出用 fontFamily('monospace') 等宽字体渲染,方便阅读 JSON 结构;解析失败时,显示红色错误卡片:
if (this.errorMsg.length > 0) {
Text(this.errorMsg)
.fontColor('#DC2626')
.backgroundColor('#FEE2E2')
} else {
Scroll() {
Text(this.jsonOut)
.fontSize(12)
.fontFamily('monospace')
}
.height(260)
}
4.7 页面进入时自动解析
aboutToAppear(): void {
this.parseXml();
}
进入页面即对默认 XML 执行一次解析,用户无需手动触发。
五、几个实战要点与坑
5.1 ConvertXML 类实例化
API 14 开始,推荐使用 new convertxml.ConvertXML() 创建解析器实例,再调用实例方法 fastConvertToJSObject()。旧版的命名空间级函数 convertToJSObject 和 convert 已标记 @deprecated since 14,在 API 24 项目中虽然声明文件里还存在,但 ArkTS 严格模式下编译器可能无法正确解析。
正确用法:
const converter: convertxml.ConvertXML = new convertxml.ConvertXML();
const result: Object = converter.fastConvertToJSObject(xml, opts);
错误用法(编译可能失败):
const result = convertxml.convertToJSObject(xml, opts); // ❌
5.2 ConvertOptions 的完整属性
ArkTS 严格模式要求对象字面量必须对应显式声明的接口或类,且接口中的非可选属性必须全部提供。ConvertOptions 有 18 个属性,其中 trim 和全部 11 个键名属性都是必填的。漏掉任何一个都会触发编译错误 arkts-no-untyped-obj-literals。
建议:在项目中声明一个与 SDK 接口完全兼容的 options 接口,每次都传完整属性。键名属性用默认值即可,不影响实际解析语义。
5.3 XML 格式错误处理
当 XML 字符串格式不合法时(比如标签不闭合、属性引号不匹配),fastConvertToJSObject 会抛出 BusinessError,错误码为 10200002。建议始终用 try-catch 包裹解析调用,给用户友好的错误提示。
try {
const result = converter.fastConvertToJSObject(this.xml, opts);
} catch (e) {
this.errorMsg = 'XML 解析失败,请检查格式';
}
5.4 忽略声明的默认建议
ignoreDeclaration(XML 声明 <?xml version="1.0"?>)和 ignoreDoctype(DTD 声明)在绝大多数业务场景中都是噪音,建议设为 true。唯一需要声明信息的情况是你要做 XML 格式转换/重写工具,才需要保留。
5.5 ignoreAttributes 对数据完整性的影响
关闭属性解析会让带有属性的元素丢失关键信息。例如:
<product id="P001" category="电子">
开启 ignoreAttributes 后,id 和 category 都不会出现在结果中。在处理以属性承载核心数据的 XML(如 SVG、XAML)时,务必保持 ignoreAttributes: false。
六、典型应用场景
- RSS/Atom Feed 解析:读取博客、新闻源的聚合内容,提取标题、链接、发布日期
- 配置文件解析:处理基于 XML 的服务器配置、数据库连接配置、权限配置等
- SOAP 接口对接:企业系统的 WebService 接口大多基于 XML,自动解析响应体
- SVG 元数据提取:读取 SVG 中的图层名、尺寸、关键字等信息
- 跨平台数据交换:Android/iOS 应用中常见的 XML 数据格式(plist、strings.xml 等),在鸿蒙端直接解析处理
- 办公文档处理:OOXML 格式(.docx/.xlsx)本质上是 XML,解析 metadata、提取内容等需求可用此 API 作为基础
七、小结
本文以"XML 解析实验室"为载体,系统讲解了 HarmonyOS NEXT 的 @ohos.convertxml:
- 核心 API:
ConvertXML类 +fastConvertToJSObject方法,一行代码将 XML 转为 JS 对象 - ConvertOptions:7 个行为开关控制解析细节,11 个键名属性定制输出结构
- 解析选项效果:trim、ignoreComment、ignoreAttributes、ignoreCDATA、ignoreInstruction 各自对输出的影响
- 工程要点:使用
new ConvertXML()实例化(非命名空间级函数)、ConvertOptions 必须提供所有必填属性、try-catch 防护 XML 格式错误、根据业务场景选择忽略/保留的内容 - 实际应用:RSS 解析、配置文件处理、SOAP 接口对接、SVG 元数据提取等
JSON 是数据交换的通用语,但 XML 仍然深深嵌入企业基础设施。@ohos.convertxml 让你不必再纠结于标签和属性,用结构化对象去思考和处理数据——这才是现代开发该有的体验。
更多推荐



所有评论(0)