如何解决 XMLParser.ErrorCode.invalidCharacterError in ios swift?
how to solve XMLParser.ErrorCode.invalidCharacterError in ios swift?
我有一项作业需要阅读一些 rss 提要和建立用户资料等。
我的问题是当我从基础使用 XMLParser 时,我会遇到 "The operation couldn’t be completed. (NSXMLParserErrorDomain error 9.)"
我查看了文档,似乎遇到了 invalidCharacterError。我认为我的代码没有问题,因为它适用于另一个 url 提要。那么我应该怎么做才能克服这个问题呢?
这是url:http://halley.exp.sis.pitt.edu/comet/utils/_rss.jsp?v=bookmark&user_id=3600
P.S。此提要包含 CDATA,所以我注释掉了标题和描述,但它应该显示日期,但它仍然显示该错误。所以我担心的是,在解析 xml 期间,它遇到了任何无效字符并报告错误。无论如何要修复它?不过我必须使用这个 url。
和一些相关代码在这里:
func parseFeed(url: String, completionHandler: (([RSSItem]) -> Void)?)
{
self.parserCompletionHandler = completionHandler
let request = URLRequest(url: URL(string: url)!)
let urlSession = URLSession.shared
let task = urlSession.dataTask(with: request) { (data, response, error) in
guard let data = data else {
if let error = error {
print(error.localizedDescription)
}
return
}
/// parse our xml data
let parser = XMLParser(data: data)
parser.delegate = self
parser.parse()
}
task.resume()
}
// MARK: - XML Parser Delegate
func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:])
{
currentElement = elementName
if currentElement == "item" {
currentTitle = ""
currentDescription = ""
currentPubDate = ""
}
}
func parser(_ parser: XMLParser, foundCharacters string: String)
{
switch currentElement {
// case "title": currentTitle += string
// case "description" : currentDescription += string
case "pubDate" : currentPubDate += string
default: break
}
}
func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?)
{
if elementName == "item" {
let rssItem = RSSItem(title: currentTitle, description: currentDescription, pubDate: currentPubDate)
self.rssItems.append(rssItem)
}
}
func parserDidEndDocument(_ parser: XMLParser) {
parserCompletionHandler?(rssItems)
}
func parser(_ parser: XMLParser, parseErrorOccurred parseError: Error)
{
print(parseError.localizedDescription)
}
我在您显示的 URL 的响应中的 CDATA
元素之一内发现了一个无效字节 0xFC。
这在声明 encoding="UTF-8"
的文档中作为 UTF-8 字节是无效的。
你最好告诉 URL 的服务器工程师,RSS 提要的 XML 无效。
如果您需要处理这种格式错误的 XML,您需要将其转换为有效的 UTF-8 数据。
0xFC 在 ISO-LATIN-1 中代表 ü
,所以你可以这样写。
func parseFeed(url: String, completionHandler: (([RSSItem]) -> Void)?)
{
self.parserCompletionHandler = completionHandler
let request = URLRequest(url: URL(string: url)!)
let urlSession = URLSession.shared
let task = urlSession.dataTask(with: request) { (data, response, error) in
guard var data = data else { //###<-- `var` here
if let error = error {
print(error.localizedDescription)
}
return
}
//### When the input `data` cannot be decoded as a UTF-8 String,
if String(data: data, encoding: .utf8) == nil {
//Interpret the data as an ISO-LATIN-1 String,
let isoLatin1 = String(data: data, encoding: .isoLatin1)!
//And re-encode it as a valid UTF-8
data = isoLatin1.data(using: .utf8)!
}
/// parse our xml data
let parser = XMLParser(data: data)
parser.delegate = self
parser.parse()
}
task.resume()
}
如果您需要处理其他编码,问题会更加困难,因为很难正确估计文本编码。
您可能需要实施 func parser(_ parser: XMLParser, foundCDATA CDATABlock: Data)
,但这似乎是另一个问题。
我有一项作业需要阅读一些 rss 提要和建立用户资料等。
我的问题是当我从基础使用 XMLParser 时,我会遇到 "The operation couldn’t be completed. (NSXMLParserErrorDomain error 9.)"
我查看了文档,似乎遇到了 invalidCharacterError。我认为我的代码没有问题,因为它适用于另一个 url 提要。那么我应该怎么做才能克服这个问题呢?
这是url:http://halley.exp.sis.pitt.edu/comet/utils/_rss.jsp?v=bookmark&user_id=3600
P.S。此提要包含 CDATA,所以我注释掉了标题和描述,但它应该显示日期,但它仍然显示该错误。所以我担心的是,在解析 xml 期间,它遇到了任何无效字符并报告错误。无论如何要修复它?不过我必须使用这个 url。
和一些相关代码在这里:
func parseFeed(url: String, completionHandler: (([RSSItem]) -> Void)?)
{
self.parserCompletionHandler = completionHandler
let request = URLRequest(url: URL(string: url)!)
let urlSession = URLSession.shared
let task = urlSession.dataTask(with: request) { (data, response, error) in
guard let data = data else {
if let error = error {
print(error.localizedDescription)
}
return
}
/// parse our xml data
let parser = XMLParser(data: data)
parser.delegate = self
parser.parse()
}
task.resume()
}
// MARK: - XML Parser Delegate
func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:])
{
currentElement = elementName
if currentElement == "item" {
currentTitle = ""
currentDescription = ""
currentPubDate = ""
}
}
func parser(_ parser: XMLParser, foundCharacters string: String)
{
switch currentElement {
// case "title": currentTitle += string
// case "description" : currentDescription += string
case "pubDate" : currentPubDate += string
default: break
}
}
func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?)
{
if elementName == "item" {
let rssItem = RSSItem(title: currentTitle, description: currentDescription, pubDate: currentPubDate)
self.rssItems.append(rssItem)
}
}
func parserDidEndDocument(_ parser: XMLParser) {
parserCompletionHandler?(rssItems)
}
func parser(_ parser: XMLParser, parseErrorOccurred parseError: Error)
{
print(parseError.localizedDescription)
}
我在您显示的 URL 的响应中的 CDATA
元素之一内发现了一个无效字节 0xFC。
这在声明 encoding="UTF-8"
的文档中作为 UTF-8 字节是无效的。
你最好告诉 URL 的服务器工程师,RSS 提要的 XML 无效。
如果您需要处理这种格式错误的 XML,您需要将其转换为有效的 UTF-8 数据。
0xFC 在 ISO-LATIN-1 中代表 ü
,所以你可以这样写。
func parseFeed(url: String, completionHandler: (([RSSItem]) -> Void)?)
{
self.parserCompletionHandler = completionHandler
let request = URLRequest(url: URL(string: url)!)
let urlSession = URLSession.shared
let task = urlSession.dataTask(with: request) { (data, response, error) in
guard var data = data else { //###<-- `var` here
if let error = error {
print(error.localizedDescription)
}
return
}
//### When the input `data` cannot be decoded as a UTF-8 String,
if String(data: data, encoding: .utf8) == nil {
//Interpret the data as an ISO-LATIN-1 String,
let isoLatin1 = String(data: data, encoding: .isoLatin1)!
//And re-encode it as a valid UTF-8
data = isoLatin1.data(using: .utf8)!
}
/// parse our xml data
let parser = XMLParser(data: data)
parser.delegate = self
parser.parse()
}
task.resume()
}
如果您需要处理其他编码,问题会更加困难,因为很难正确估计文本编码。
您可能需要实施 func parser(_ parser: XMLParser, foundCDATA CDATABlock: Data)
,但这似乎是另一个问题。