ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

一段XML少了前后文字:HarmonyOS 7修复混合内容解析后,正文提取和快照测试一起改

一段XML少了前后文字:HarmonyOS 7修复混合内容解析后,正文提取和快照测试一起改 一段XML少了前后文字HarmonyOS 7修复混合内容解析后正文提取和快照测试一起改阅读器导入一段带强调标记的说明“请先”在标记前“再继续”在标记后。旧版本导入结果只剩中间的强调词界面看起来像内容缺了一半。升级后文字恢复了原来的快照测试却开始失败原因不是新的解析器把顺序弄乱而是旧代码和测试一起接受了错误结果。HarmonyOS 7修复了ConvertXML.fastConvertToJSObject解析混合内容时丢失同级文本节点的问题。本文把升级拆成两个不同任务普通正文要按文档顺序保留文字结构化记录不能继续假定_elements[0]一定是子元素。官方Beta1变更页更新于2026年8月19日9月28日再次核对。本文对文档给出的解析结果结构编写遍历代码并执行宿主断言没有在本机运行HarmonyOS ConvertXML也没有把Node.js测试说成API26编译或设备结果。修复的不是整个XML标准而是一个具体丢字问题对于“文本、子元素、文本”混排的内容变更前子元素旁边的文本可能丢失变更后同级文本会保留。接口从API14提供本次修复不是新增加一个转换器。官方汇总将此项列为全部生效不能只靠降低targetSdkVersion回避测试。可以在支持环境中用以下自写输入观察结果import { convertxml } from kit.ArkTS; const converter new convertxml.ConvertXML(); const xml notice请先strong保存/strong再继续/notice; const result converter.fastConvertToJSObject(xml); console.info(JSON.stringify(result));这段输入没有文件访问或网络请求。输出应包含notice内部前、中、后三段文字对应的节点。若工程使用了ConvertOptions应把选项与结果一起保存本文后续适配针对官方变更示例中的非紧凑_elements结构不声称适用于所有自定义转换选项。案例一提取可阅读正文但不要破坏空白常见错误是只遍历_type为element的节点然后取它们的文本。修复后新出现的同级text节点仍然会被应用代码忽略。另一种错误是每个文本节点先trim再拼接结果英文词之间的空格消失。下面把输出节点建模为最小结构。输入来自转换器输出适配不是在手写XML解析器type XmlNode { _type: string; _name?: string; _text?: string; _elements?: XmlNode[] }; function plainText(nodes: XmlNode[]): string { const pieces: string[] []; for (const node of nodes) { if (node._type text) pieces.push(node._text ?? ); else if (node._type element) pieces.push(plainText(node._elements ?? [])); } return pieces.join(); } function assertEqual(actual: unknown, expected: unknown): void { if (JSON.stringify(actual) ! JSON.stringify(expected)) throw new Error(assertion failed); } const mixed: XmlNode[] [ { _type:text, _text:请先 }, { _type:element, _name:strong, _elements:[{ _type:text, _text:保存 }] }, { _type:text, _text:再继续 } ]; assertEqual(plainText(mixed), 请先保存再继续); const english: XmlNode[] [ { _type:text, _text:read }, { _type:element, _name:b, _elements:[{ _type:text, _text:this }] }, { _type:text, _text: first } ]; assertEqual(plainText(english), read this first);这里不逐段trim因为相邻标签之间的空格也可能有语义。如果产品只需要搜索索引可以在最终文本上另做空白规范化但应明确这是搜索层策略不能回写替换原始正文。本文两个案例只处理text与element不处理CDATA、注释和处理指令。需要这些节点时应按当前转换选项的实际输出另加适配和样本不能把这个最小结构当成完整的XML数据模型。递归遍历适合受控的小型说明文档。面对不可信、可能极深的结构需要输入大小和深度约束避免递归栈被耗尽。本文不会以“几行递归”声称解决了全部XML安全问题。同一段内容需要保留强调样式怎么办纯文本不是富文本。提取成字符串后strong这样的语义已经丢失。若阅读器需要保留样式应在遍历时产生有序片段而不是先拼接再根据关键词重新定位type Run { text: string; strong: boolean }; function textRuns(nodes: XmlNode[], strong false): Run[] { const result: Run[] []; for (const node of nodes) { if (node._type text) { result.push({ text:node._text ?? , strong }); } else if (node._type element) { result.push(...textRuns(node._elements ?? [], strong || node._name strong)); } } return result; } assertEqual(textRuns(mixed), [ {text:请先,strong:false}, {text:保存,strong:true}, {text:再继续,strong:false} ]);片段结果可以再转换为ArkUI可渲染内容。这里仅支持strong演示语义未知标签被作为容器继续遍历没有执行标签携带的脚本或外部资源。链接、图片、列表等需要各自定义白名单和资源处理不能直接把所有节点塞进HTML执行。案例二配置记录前多了空白首元素不再是记录另一个场景不是正文而是应用导入的结构化条目。历史代码把root._elements[0]当成record升级后首项可能变成前导文本节点。更隐蔽的是某份文件没有空白所以正常另一份经过格式化就失败。正确的选择应按节点类型和名称不靠数组位置function childElements(nodes: XmlNode[], name: string): XmlNode[] { return nodes.filter(node node._type element node._name name); } const records: XmlNode[] [ {_type:text,_text:\n }, {_type:element,_name:record,_elements:[{_type:text,_text:甲}]}, {_type:text,_text:\n }, {_type:element,_name:record,_elements:[{_type:text,_text:乙}]}, {_type:text,_text:\n} ]; assertEqual(childElements(records,record).map(xplainText(x._elements ?? [])), [甲,乙]); assertEqual(childElements(records,missing), []); assertEqual(records[0]._type, text);这不意味着可以全局删除所有text节点。配置读取器只是在当前位置寻找record正文读取器仍需要保留文本。把两种目的封装成不同函数比给一个通用函数加多个含糊开关更不容易误用。快照测试失败先判断差异属于哪一类升级时不要直接把新JSON覆盖成“正确快照”。至少应做三件事原始XML中确有这些文字新节点顺序与原文顺序一致业务最终输出保留了应有内容。满足这三项才可以把丢失文字的旧快照视作需要修正的基线。变化应如何处理多出原文确实存在的同级text更新结构与正文断言检查旧代码是否按下标取元素只有空白节点变化明确正文与配置场景各自是否保留空白丢失子元素内容或顺序颠倒不能直接接受核对转换选项和适配层业务输出相同但序列化不同分离结构快照与语义断言避免只比较JSON字符串我更倾向保留少量结构快照加上明确的语义断言混合段落的完整文本、强调范围、记录数量、记录顺序。只看结构会对实现细节过敏只看拼接文本又可能漏掉样式丢失两者需要互补。把变化关在一个适配层里迁移时可以按“ConvertXML原始结果 → 应用XmlNode结构 → 正文/记录读取器”组织。边界层校验字段类型和深度业务层只处理已知结构。这样未来转换选项或输出形式再变化影响范围不会扩散到每个页面。不要把转换器的结果强行断言为完整业务对象后直接读字段。类型断言不执行运行时验证。本文为了说明节点顺序测试输入是手写的有效结构生产导入需要增加unknown输入校验并将格式错误作为可恢复错误返回给界面。升级验收顺序先准备纯文本、纯子元素、混合内容三份最小XML再加入空白、嵌套强调和空记录。用旧环境与API26环境分别保存原始转换输出检查与官方说明是否一致随后运行本文业务遍历断言最后检查页面是否保留文字与样式。本文宿主测试覆盖的是后半段“转换结果到业务输出”不是前半段系统转换器实现。真实设备补测时应把系统版本、SDK版本、ConvertOptions和输入样本一起记录这比一句“升级后好了”更能帮助下一次排查。这次修复带来的价值不是多了几个JSON节点而是应用终于能拿到原文完整的表达。接下来要做的是删掉对旧缺陷的依赖而不是再写一层过滤把新保留的文字丢掉。参考资料官方ConvertXML混合内容解析修复说明API26行为变更汇总升级适配指导
返回列表