Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

XML Parsing getting string inside brakets <something="How to get this string">

Here is a sample of the XML data I am trying to parse. Im having trouble figuring out how to parse the data inside the "" that is nested within the brackets i.e <something="How to get this string">. here for example id want to get "How to get this string". I am able to get the Data if its in between the opening and closing carrots I Got this.

<METAR>
   <sky_condition sky_cover="OVC" cloud_base_ft_agl="2100"/> <---- get the OVC from sky_cover
   <flight_category>IFR</flight_category>
   <metar_type>METAR</metar_type>
</METAR>

Here is my XML Parser Code & Delegate functions

import Foundation

class FeedParser: NSObject, XMLParserDelegate {
    private var airportItems: [FlightCategory] = [] // track parsing
    private var currentAirportElement: String = "" // track current item being parsed
    private var parserCompletiongHandler: (([FlightCategory]) -> Void)? // handle completion of parsing
    
    private var currentAirportFlightCategory: String = "" {
        didSet {
            // trim whitespace
            currentAirportFlightCategory = currentAirportFlightCategory.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
        }
    }
    
    private var currenAirportSkyCondition: String = "" {
        didSet {
            currenAirportSkyCondition = currenAirportSkyCondition.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
        }
    }
    
    // MARK: - URL Request
    
    // Hnadle Parsing feed
    func parseFeed(url: String, completionHandler: (([FlightCategory]) -> Void)?) {
        self.parserCompletiongHandler = completionHandler
        
        // URL Session Reques
        let request = URLRequest(url: URL(string: url)!)
        let session = URLSession.shared
        
        let task = session.dataTask(with: request) { data, response, error in
            
            // if no data
            guard let data = data else {
                if let error = error {
                    print(error.localizedDescription)
                }
                
                return
            }
            
            // if data
            // parse 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] = [:]) {
        // track current item
        currentAirportElement = elementName
        if currentAirportElement == "METAR" { // it is there
            // currentAirportElement = ""
            
            currentAirportFlightCategory = ""
            currenAirportSkyCondition = ""
        }
    }
    
    // Once Parser get values of element Handler
    func parser(_ parser: XMLParser, foundCharacters string: String) {
        switch currentAirportElement {
        case "flight_category": currentAirportFlightCategory += string
                
        default: break
        }
    }
    
    // Once Parser at End of element Handler
    func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
        if elementName == "METAR" { // "flight_category"
            let airportItems = FlightCategory(flight_category: currentAirportFlightCategory, sky_condition: currenAirportSkyCondition)
            self.airportItems.append(airportItems)
        }
    }
    
    // Call Completion Handler upon finishing Parsing
    func parserDidEndDocument(_ parser: XMLParser) {
        parserCompletiongHandler?(airportItems)
    }
    
    // Handle Parsing Errors
    func parser(_ parser: XMLParser, parseErrorOccurred parseError: any Error) {
        print(parseError.localizedDescription)
    }
}

And here is how I am loading the XML

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

private func loadXMLData() async {
        print("hmmmmm")
        let acwXMLURL = "https://aviationweather.gov/api/data/dataserver?requestType=retrieve&dataSource=metars&stationString=\KVNY&startTime=2024-03-10T21%3A44%3A22Z&format=xml&mostRecent=true"
        
        // parser feeder
        let feeder = FeedParser()
        feeder.parseFeed(url: acwXMLURL) { data in
            self.detaileHomeAirportXML = data
        }
    }
    
    private func handleXMLData() async {
        detaileHomeAirportXML?.forEach { item in
            currentFltCat = item.flight_category
            model.airportFltCat = item.flight_category
            print("XML data handled: \(currentFltCat)")
            
            if currentFltCat == "VFR" {
                color = Color(.green)
            } else if currentFltCat == "MVFR" {
                color = Color(.blue)
            } else if currentFltCat == "IFR" {
                color = Color(.red)
            } else if currentFltCat == "LIFR" {
                color = Color(red: 208 / 255, green: 45 / 255, blue: 208 / 255)
            }
        }
    }

>Solution :

In the didStartElement delegation function, you receive an attributes dictionary. This contains the attributes of the tag.

You would write something like –

func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {
       
        switch(elementName) {
            case "METAR":
                currentAirportFlightCategory = ""
                currenAirportSkyCondition = ""
            case "sky_condition":
                skyCover = attributes["sky_cover"]
                cloudBase = attributes["cloud_base_ft_agl"]
            default:
                print("Ignoring element \(elementName)")
        }
    }

Note that these will be optional strings, so you need to handle that and convert to integer as required.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading