从 url 在 iOS Swift 中解析 xml

Parsing xml from from url in iOS Swift

    <?xml version="1.0" encoding="utf-8"?>
    <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <soap:Body>
            <CreditCheckMSResponse xmlns="https://ebs.gsm.co.za/">
                <CreditCheckMSResult>
                    <result message="Success" ref="505790" network="CellC" xmlns="" />
                </CreditCheckMSResult>
            </CreditCheckMSResponse>
        </soap:Body>
    </soap:Envelope>

这是我的尝试:

let parser = XMLParser(data: data)
 parser.delegate = self
 if parser.parse() {
     print(self.results ?? "No results")
 }
 let recordKey = "result"
    let dictionaryKeys = Set<String>(["message", "ref", "network", "xmlns"])

    // a few variables to hold the results as we parse the XML

    var results: [[String: String]]?         // the whole array of dictionaries
    var currentDictionary: [String: String]? // the current dictionary
    var currentValue: String?                // the current value for one of the keys in the dictionary
    


    extension ViewController: XMLParserDelegate {
    
        // initialize results structure
    
        func parserDidStartDocument(_ parser: XMLParser) {
            results = []
        }
    
        // start element
        //
        // - If we're starting a "record" create the dictionary that will hold the results
        // - If we're starting one of our dictionary keys, initialize `currentValue` (otherwise leave `nil`)
    
        func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {
            if elementName == recordKey {
                currentDictionary = [String : String]()
            } else if dictionaryKeys.contains(elementName) {
                currentValue = String()
            }
        }
    
        // found characters
        //
        // - If this is an element we care about, append those characters.
        // - If `currentValue` still `nil`, then do nothing.
    
        func parser(_ parser: XMLParser, foundCharacters string: String) {
            currentValue? += string
        }
    
        // end element
        //
        // - If we're at the end of the whole dictionary, then save that dictionary in our array
        // - If we're at the end of an element that belongs in the dictionary, then save that value in the dictionary
    
        func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
    
            if elementName == recordKey {
                results!.append(currentDictionary!)
                currentDictionary = nil
            } else if dictionaryKeys.contains(elementName) {
                currentDictionary![elementName] = currentValue
                currentValue = nil
            }
        }
    
        // Just in case, if there's an error, report it. (We don't want to fly blind here.)
    
        func parser(_ parser: XMLParser, parseErrorOccurred parseError: Error) {
            print(parseError)
    
            currentValue = nil
            currentDictionary = nil
            results = nil
        }
    
    }

如有任何帮助,我们将不胜感激!

提前致谢!

从你的问题中不能完全清楚你的目标是什么,但我假设它是提取 CreditCheckMSResult 元素中包含的 result 元素的属性。

这些值是 result 元素的属性,而不是子元素。因此,当您在 didStartElement 中获取 result 元素的开头时,您想要的值位于传递给该函数的 attributes 字典中。

字典很少是好的最终数据模型。在这种情况下,我建议您创建一个结构数组来包含您的数据。

struct CreditCheckResult {
    let message: String
    let ref: String
    let network: String
}

xmlns 属性用于详细说明应用到元素的 XML 名称空间(如果有的话)。你不想存储这个。

因为您对 result 元素的子元素不感兴趣(它没有)。您几乎只需要 didStart 委托方法。

let recordKey = "result"
let results = [CreditCheckResult]?
extension ViewController: XMLParserDelegate {

    func parserDidStartDocument(_ parser: XMLParser) {
        results = []
    }
    
    func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {

        // We only care about "result" elements
         guard elementName == recordKey else {
             return
         }

         guard let message = attributes["message"],
               let ref = attributes["ref"],
               let network = attributes["network"] else {
                   print("Malformed result element = required attribute missing")
                   return
         }
 
         self.results?.append(CreditCheckResult(message: message, ref: ref, network:network))
    }

    func parser(_ parser: XMLParser, parseErrorOccurred parseError: Error) {
        print(parseError)
        results = []
    }

}