xmlparser 解析失败却不报错,因 delegate 被提前释放导致回调静默失效;解析中文乱码需显式指定编码;foundcharacters: 可能分段回调,应累积处理;命名空间需手动拆解。

XMLParser 解析失败却没报错?检查 delegate 是否被提前释放
Swift 里 XMLParser 是委托式异步解析器,不持有 delegate,一旦 delegate 实例(比如 ViewController)被释放,后续回调就静默失效——不会 crash,也不会进 parserDidEndDocument:,看起来就像“卡住”或“没解析”。
- 常见现象:
parserDidStartElement:只触发几次就停了,parserDidEndDocument:完全不调用,控制台也无错误 - 典型场景:在
viewDidLoad里初始化XMLParser,但 parser 是局部变量,或 delegate 是临时对象 - 必须确保 parser 和 delegate 都是强引用,且生命周期至少覆盖整个解析过程
- 推荐写法:把
XMLParser声明为类属性(var parser: XMLParser?),并让当前类(如 ViewModel)同时遵守XMLParserDelegate
解析中文或特殊字符时内容乱码?确认 encoding 显式指定
XMLParser 默认按 UTF-8 解析,但如果 XML 声明里写了 <?xml version="1.0" encoding="GB2312"?> 或服务端返回 header 没带 charset,实际数据却是 GBK 编码,就会出现 parser:foundCharacters: 返回乱码字符串。
- 不要依赖 XML 声明自动识别——
XMLParser根本不读取 encoding 属性,它只认输入数据的原始字节流编码 - 务必在构建
Data时明确指定编码:Data(xmlString.utf8)是安全的;若从网络拿到Data,需确认服务器响应 header 的Content-Type是否含charset=gbk - 如果后端固定发 GBK,用
String(data: data, encoding: .gbk)转一次再喂给 parser(iOS 13+ 支持.gbk,旧系统需用CFStringConvertEncodingToNSStringEncoding)
parser:foundCharacters: 返回空字符串?注意空白符和分段回调
XMLParser 不保证一次回调就把一个文本节点传全,尤其当内容较长或含换行/缩进时,parser:foundCharacters: 可能被多次调用,中间夹着 parser:foundIgnorableWhitespace:。
- 常见错误:每次进
foundCharacters:就直接赋值currentValue = string,结果只保留最后一段 - 正确做法:用可变字符串累积,例如声明
var currentText = String(),在foundCharacters:里执行currentText += string - 别忽略
foundIgnorableWhitespace:——它可能包含换行、空格,是否保留取决于业务(如配置文件要保留,纯数据可 trim) - 在
parser:didEndElement:里处理完currentText后,记得清空:currentText = ""
想解析带命名空间的 XML?XMLParser 本身不支持,得手动拆解
XMLParser 对 xmlns、xmlns:xsi 这类声明完全无视,也不会帮你把 ns:tag 中的前缀映射到 URI。所有元素名、属性名都原样透传,包括冒号。
- 现象:
parser:didStartElement:的elementName是"soap:Body",不是"Body";attributeDict里也可能有"xsi:type" - 没有内置 namespace 解析逻辑,别指望设置某个 flag 就能自动剥离前缀
- 实用策略:在
didStartElement:里用elementName.split(separator: ":").last ?? elementName提取本地名(注意判断 nil) - 更稳妥的做法:改用第三方库(如
SWXMLHash),或者升级到 iOS 17+ 考虑XMLDocument(但需注意它不支持流式解析)
真正麻烦的不是语法,是命名空间混用时元素名动态变化、前缀不统一——这时候靠字符串切分容易漏,得结合上下文状态机来判别。










