在 iOS Swift 中解析来自 url 的 xml

Parsing xml from from url in iOS Swift

提问人:Mukesh Lokare 提问时间:3/15/2021 最后编辑:Mukesh Lokare 更新时间:3/15/2021 访问量:742

问:

    <?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
        }
    
    }

任何帮助将不胜感激!

提前谢谢你!

iOS Swift XML 解析

评论


答:

1赞 Paulw11 3/15/2021 #1

从您的问题中并不完全清楚您的目标是什么,但我认为它是提取元素中包含的元素的属性。resultCreditCheckMSResult

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

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

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

该属性用于详细说明与元素相关的 XML 命名空间(如果有)。你不会想存储这个。xmlns

由于您对元素的子元素不感兴趣(它没有任何子元素)。您几乎只需要委托方法。resultdidStart

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 = []
    }

}

评论

0赞 Mukesh Lokare 3/15/2021
您好@Paulw11,非常感谢您的帮助。我不知道技巧就是这么简单。您能否向我发送任何使用 swift 解析 XML 的最佳参考资料。