用 Swift 实现的简单 XML 解析器
这是一个受 SwiftyJSON 和 SWXMLHash 启发的 XML 解析器。
Foundation 框架中的 NSXMLParser 是一种 “SAX” 解析器。它性能足够,但有点不方便。因此,我们实现了封装它的 “DOM” 解析器。
github "https://github.com/yahoojapan/SwiftyXMLParser"
> carthage update
platform :ios, '9.0'
use_frameworks!
pod "SwiftyXMLParser", :git => 'https://github.com/yahoojapan/SwiftyXMLParser.git'
> pod install
import SwiftyXMLParser
let str = """
<ResultSet>
<Result>
<Hit index=\"1\">
<Name>Item1</Name>
</Hit>
<Hit index=\"2\">
<Name>Item2</Name>
</Hit>
</Result>
</ResultSet>
"""
// parse xml document
let xml = try! XML.parse(str)
// access xml element
let accessor = xml["ResultSet"]
// access XML Text
if let text = xml["ResultSet", "Result", "Hit", 0, "Name"].text {
print(text)
}
if let text = xml.ResultSet.Result.Hit[0].Name.text {
print(text)
}
// access XML Attribute
if let index = xml["ResultSet", "Result", "Hit", 0].attributes["index"] {
print(index)
}
// enumerate child Elements in the parent Element
for hit in xml["ResultSet", "Result", "Hit"] {
print(hit)
}
// check if the XML path is wrong
if case .failure(let error) = xml["ResultSet", "Result", "TypoKey"] {
print(error)
}
let str = """
<ResultSet>
<Result>
<Hit index=\"1\">
<Name>Item1</Name>
</Hit>
<Hit index=\"2\">
<Name>Item2</Name>
</Hit>
</Result>
</ResultSet>
"""
xml = try! XML.parse(str) // -> XML.Accessor
let str = """
<ResultSet>
<Result>
<Hit index=\"1\">
<Name>Item1</Name>
</Hit>
<Hit index=\"2\">
<Name>Item2</Name>
</Hit>
</Result>
</ResultSet>
"""
let string = String(decoding: data, as: UTF8.self)
xml = XML.parse(data) // -> XML.Accessor
let srt = "<xmlopening>@ß123\u{1c}</xmlopening>"
let xml = XML.parse(str.data(using: .utf8))
if case .failure(XMLError.interruptedParseError) = xml {
print("invalid character")
}
更多信息,请参阅 https://developer.apple.com/documentation/foundation/xmlparser/errorcode
let element = xml.ResultSet // -> XML.Accessor
let element = xml["ResultSet"]["Result"] // -> <Result><Hit index=\"1\"><Name>Item1</Name></Hit><Hit index=\"2\"><Name>Item2</Name></Hit></Result>
let path = ["ResultSet", "Result"]
let element = xml[path] // -> <Result><Hit index=\"1\"><Name>Item1</Name></Hit><Hit index=\"2\"><Name>Item2</Name></Hit></Result>
let element = xml["ResultSet", "Result"] // -> <Result><Hit index=\"1\"><Name>Item1</Name></Hit><Hit index=\"2\"><Name>Item2</Name></Hit></Result>
let element = xml.ResultSet.Result // -> <Result><Hit index=\"1\"><Name>Item1</Name></Hit><Hit index=\"2\"><Name>Item2</Name></Hit></Result>
let element = xml.ResultSet.Result.Hit[1] // -> <Hit index=\"2\"><Name>Item2</Name></Hit>
if let attributeValue = xml.ResultSet.Result.Hit[1].attributes?["index"] {
print(attributeValue) // -> 2
}
if let text = xml.ResultSet.Result.Hit[1].Name.text {
print(text) // -> Item2
}
struct Entity {
var name = ""
}
let entity = Entity()
entity.name ?= xml.ResultSet.Result.Hit[1].Name.text // assign if it has text
struct Entity {
var name: Int = 0
}
let entity = Entity()
entity.name ?= xml.ResultSet.Result.Hit[1].Name.int // assign if it has Int
还有其他语法糖,bool、url 和 double。
struct Entity {
var names = [String]()
}
let entity = Entity()
entity.names ?<< xml.ResultSet.Result.Hit[1].Name.text // assign if it has text
let str = """
<Data name="DATE">
<value><![CDATA[2018-07-08]]></value>
</Data>
"""
// parse xml document
let xml = try! XML.parse(str)
if let cdata = xml.Data.value.element?.CDATA,
let cdataStr = String(data: cdata, encoding: .utf8) {
print(cdataStr) // -> "2018-07-08"
}
let numberOfHits = xml.ResultSet.Result.Hit.all?.count
print(xml.ResultSet.Result.TypoKey) // -> "TypoKey not found."
for element in xml.ResultSet.Result.Hit {
print(element.text)
}
xml.ResultSet.Result.Hit.map { $0.Name.text }
print(Converter(xml.ResultSet).makeDocument())
SwiftyXMLParser 与 Alamofire 配合良好。您可以轻松解析响应。
import Alamofire
import SwiftyXMLParser
Alamofire.request(.GET, "https://itunes.apple.com/us/rss/topgrossingapplications/limit=10/xml")
.responseData { response in
if let data = response.data {
let xml = XML.parse(data)
print(xml.feed.entry[0].title.text) // outputs the top title of iTunes app raning.
}
}
此外,还有 Alamofire 的扩展可以与 SwiftyXMLParser 结合使用。
当前 master 分支 支持 Xcode 10。如果您想将此库与旧版本的 Swift 一起使用,请阅读发行说明并安装最后一个兼容版本。
本软件根据 MIT 许可证发布,请参阅 LICENSE 文件。