在 swift 中解析具有相同名称的 XML 个子标签

Parse XML subtags with same name in swift

我是 swift 的新手。我创建了一个 XML 解析器,一个一个地读取每个标签(标签和子标签)。我发现的问题是有一些同名的子标签,所以我的代码无法区分。我需要知道如何读取具体的子标签以区分并将其存储在不同的变量中。

这是我正在解析的XML(缩减):

<_0:situationRecord id="GUID_Suc_3971318_3971318" xsi:type="_0:NetworkManagement">
    <_0:identifier>171826</_0:identifier>
    <_0:to xsi:type="_0:TPEGNonJunctionPoint">
        <_0:name>
            <_0:descriptor>
                <_0:value>MADRID</_0:value>
            </_0:descriptor>
            <_0:tpegDescriptorType>other</_0:tpegDescriptorType>
        </_0:name>
    </_0:to>
    <_0:from xsi:type="_0:TPEGNonJunctionPoint">
        <_0:name>
            <_0:descriptor>
                <_0:value>SANTIAGO DE COMPOSTELA</_0:value>
            </_0:descriptor>
            <_0:tpegDescriptorType>other</_0:tpegDescriptorType>
        </_0:name>
    </_0:from>
</_0:situationRecord>

这是我的 ParseINCDGT.swift class:

import Foundation

struct INCIDENCIADGT {
    var identifier: String
    var valueFrom: String
    var valueTo: String
}

class ParseINCDGT: NSObject, XMLParserDelegate {
    private var myData: Data
    private var currentElementName = ""
    private var inItem = false
    private var item: INCIDENCIADGT
    var ready = false
    
    var auxLat = 1
    var auxLong = 1
    var aux = 1
    
    var items: [INCIDENCIADGT]
    
    override init() {
        //Default values
        myData = "".data(using: .ascii)!
        items = []
        item = INCIDENCIADGT(identifier: "", valueFrom: "", valueTo: "")
    }
    
    // Set the local data set for parsing
    func setData(data: Data) -> Void {
        if data == nil {
            return
        }
        myData = data
    }
    
    // Runs the parsing process, returns at the end. Please note that this function is synchronous, while internally asynchronous
    func parse() -> Void {
        let parser = XMLParser(data: myData)
        parser.delegate = self
        parser.parse()
    }
    
    // Terminate session
    func parserDidEndDocument(_ parser: XMLParser) {
        ready = true
    }
    
    // Start session
    func parserDidStartDocument(_ parser: XMLParser) {
        ready = false
    }
    
    // Terminate an element
    func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
        currentElementName = elementName
        if elementName == "_0:situationRecord" {
            inItem = false
            items.append(item)
        }
    }
    
    // Starts an element
    func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {
        currentElementName = elementName
        if elementName == "_0:situationRecord" {
            inItem = true
            item = INCIDENCIADGT(identifier: "", valueFrom: "", valueTo: "")
        }
    }
    
    // Collects other data
    func parser(_ parser: XMLParser, foundCharacters string: String) {
        
        switch currentElementName{
        case "_0:identifier":
            item.identifier += string.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
        case "_0:value":
            item.valueFrom += string.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
        default:
            break
        }
    }
}

这是我调用 ParserINCDGT.swift:

的方法
func loadData() -> Void {
    let url = "http://infocar.dgt.es/datex2/dgt/SituationPublication/all/content.xml"
    let request = URLRequest(url: URL(string: url)!)
        
    let session3 = URLSession.shared.dataTask(with: request3) {
        (data, _, error) in
        
        //Handle errors
        if error != nil {
            //Show error message
            return
        }
        
        guard let data = data else{
            //Data error, show message
            return
        }
        
        //Convert data to string
        var s: String = String(data: data, encoding: .ascii)!
        
        //Make XML conforming to all standards: Convert LF to CR
        s = s.replacingOccurrences(of: "\r", with: "\n")
        
        //Parse XML
        let p = ParseINCDGT()
        p.setData(data: data)
        p.parse()
        
        //Elaborate data
        print(p.items)
        
        if (p.items.count != 0) {
            for item in p.items {
                print(item.identifier)
                print(item.valueFrom)
            }
        }
    }
    //Run!
    session.resume()
}

变量“valueForm”的最终输出是“MADRIDSANTIAGO DE COMPOSTELA”

谁能帮我解释一下我应该包括什么来解析和区分子标签“_0:value”?

非常感谢。感谢任何帮助。

您只需添加一些更改:

检查标签_0:from_0:to是否启动并保存在变量中,我这里叫它isFrom,你需要把它添加到你的class(私人会更好)。当您在 _0:value 中查找文本时,您将其添加到 INCIDENCIADGT 结构的正确元素中。

在这里您可以看到需要更改的两个函数以及需要添加的内容:

// Starts an element
func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {
    currentElementName = elementName
    if elementName == "_0:situationRecord" {
        inItem = true
        item = INCIDENCIADGT(identifier: "", valueFrom: "", valueTo: "")
    } else if elementName == "_0:from" { // check if we will be looking at from information when getting the next _0:value
        isFrom = true // could use an enum if more posibilities exist than from and to.
    } else if elementName == "_0:to" { // check if getting to information like above
        isFrom = false // could use an enum if more posibilities exist than from and to.
    }
}

// Collects other data
func parser(_ parser: XMLParser, foundCharacters string: String) {
    
    switch currentElementName{
    case "_0:identifier":
        item.identifier += string.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
    case "_0:value":
        if isFrom { // write the information in the right field of the struct
            item.valueFrom += string.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
        } else {
            item.valueTo += string.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
        }
    default:
        break
    }
}

我写的东西可能还有一些错误和警告,因为我只是在编辑器里做的,并没有在xcode中测试它,但如果它不起作用,它至少给出了你知道如何开始解决你的具体问题。