使用 XMLParser 在 Swift 中解析带有实体的 XML

Jul*_*ian 5 xml xml-parsing swift swift3

在 Swift 中使用 XMLParser 处理文档时,有没有办法扩展 XML 实体?我在 API 中没有看到任何内容,但我很难相信这是一个奇怪的要求。

如果直接从 Swift 使用 libxml2 API,则可以完成此操作,库通过字符回调提供扩展实体,就像它内联出现一样。

这是我的示例代码:

let xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
    "<!DOCTYPE simple [" +
    "<!ENTITY e \"entity\">" +
    "]>" +
    "<root><val>&e;</val></root>"

class ParserDelegate : NSObject, XMLParserDelegate {
    var entities = [String:String?]()
    var text: String?

    func parser(_ parser: XMLParser, foundInternalEntityDeclarationWithName name: String, value: String?) {
        self.entities[name] = value
    }

    func parser(_ parser: XMLParser, foundCharacters string: String) {
        text = text == nil ? string : self.text! + string
    }
}

let delegate = ParserDelegate()

let parser = XMLParser(data: xml.data(using: String.Encoding.utf8)!)
parser.delegate = delegate


parser.parse()

if let text = delegate.text {
    print("found text:" + text)
}

delegate.entities.forEach() {
    (entry) in let (key, val) = entry
    print(key + ": " + (val ?? "<nil>"))
}
Run Code Online (Sandbox Code Playgroud)

运行此命令时,永远不会打印“找到的文本”,因为func parser(_ parser: XMLParser, foundCharacters string: String)永远不会调用,这可以通过设置断点来验证。

输出很简单:

e: entity
Run Code Online (Sandbox Code Playgroud)

我尝试查看委托上的各种方法,但没有看到任何相关内容。该public func parser(_ parser: XMLParser, resolveExternalEntityName name: String, systemID: String?) -> Data?方法看起来很接近,但这些是内部实体,实现它不会产生有趣的结果。

编辑

看起来这确实是解析器的一个限制,可以追溯到很多年前。

我可以在 stackoverflow 上找到 2009 年以来的问题:

我在 Open Radar 上发现了 2017 年 5 月的这个项目:

libxml2 库上有一些关于实体的评论,其中指出了实体带来的一些挑战,这可能有助于解释为什么 (NS)XMLParser 的行为如此。