Saken
Saken

Reputation: 13

Swift XML attribute parsing

I have problem with XML parsing in Swift. I woul like to use AttributeDict but i have many attributes to use it. So i use Dictionary. But it's not working, And i use code in this page:

Get attibuteDict of a subclass Xml parsing - Swift

but it's still not working. Tell me if you know My XML Data:

 <root>
        <day1><day1 p1.1="-" pk1.1="-" s1.1="" a1.1="-" p1.2="-" pk1.2="-" s1.2="" a1.2="-" 
        p1.3="Начертательная геометрия и компьютерная графика" pk1.3="НГиКГ" s1.3="Оспанова З. К." 
        a1.3="127 ГМК" p1.4="Начертательная геометрия и компьютерная графика" pk1.4="НГиКГ" 
        s1.4="Оспанова З. К." a1.4="127 ГМК" p1.5="Физика" pk1.5="Физика" s1.5="Сарсембаева Б. Д." 
        a1.5="913 ГУК" p1.6="Физика" pk1.6="Физика" s1.6="Сарсембаева Б. Д." a1.6="1035 с ГУК" 
        p1.7="Физика" pk1.7="Физика" s1.7="Сарсембаева Б. Д." a1.7="913а ГУК" p1.8="Физика" 
        pk1.8="Физика" s1.8="Сарсембаева Б. Д." a1.8="913а ГУК" p1.9="Физическая культура" 
        pk1.9="ФизКульт" s1.9="Акмалиев А. Ж." a1.9=" -" p1.10="Физическая культура" pk1.10="ФизКульт" 
        s1.10="Акмалиев А. Ж." a1.10=" -" p1.11="-" pk1.11="-" s1.11="" a1.11="-" p1.12="-" pk1.12="-" 
        s1.12="" a1.12="-" p2.1="-" pk2.1="-" s2.1="" a2.1="-" p2.2="Политология" pk2.2="Полит-ия" 
        s2.2="Анапияева Г. Б." a2.2="705 ГУК" p2.3="Физика" pk2.3="Физика" s2.3="Оспанов К. М." 
        a2.3="713 ГУК" p2.4="Физика" pk2.4="Физика" s2.4="Оспанов К. М." a2.4="713 ГУК" 
        p2.5="Начертательная геометрия и компьютерная графика" pk2.5="НГиКГ" s2.5="Оспанова З. К." 
        a2.5="1035в ГУК" p2.6="Начертательная геометрия и компьютерная графика" pk2.6="НГиКГ" 
        s2.6="Оспанова З. К." a2.6="1035в ГУК" p2.7="Физическая культура" pk2.7="ФизКульт" s2.7="Акмалиев А. Ж." 
        a2.7=" -" p2.8="Физическая культура" pk2.8="ФизКульт" s2.8="Акмалиев А. Ж." a2.8=" -" p2.9="-" 
        pk2.9="-" s2.9="" a2.9="-" p2.10="-" pk2.10="-" s2.10="" a2.10="-" p2.11="-" pk2.11="-" s2.11="" a2.11="-"
        p2.12="-" pk2.12="-" s2.12="" a2.12="-" p3.1="-" pk3.1="-" s3.1="" a3.1="-" p3.2="-" pk3.2="-" s3.2="" a3.2="-"
        p3.3="Математика II" pk3.3="Матем.II" s3.3="Акимжанова Ш. А." a3.3="713 ГУК" p3.4="Математика II" 
        pk3.4="Матем.II" s3.4="Акимжанова Ш. А." a3.4="713 ГУК" p3.5="Начертательная геометрия и компьютерная графика" 
        pk3.5="НГиКГ" s3.5="Иисова А. М." a3.5="533 ГУК" p3.6="Эдвайзер" pk3.6="ЭД" s3.6="Тирижанова М. Б." 
        a3.6="517 ВК" p3.7="Начертательная геометрия и компьютерная графика" pk3.7="НГиКГ" s3.7="Курманалиева Ш. М." 
        a3.7="805 ГУК" p3.8="Начертательная геометрия и компьютерная графика" pk3.8="НГиКГ" s3.8="Курманалиева Ш. М." 
        a3.8="805 ГУК" p3.9="Начертательная геометрия и компьютерная графика" pk3.9="НГиКГ" s3.9="Курманалиева Ш. М." 
        a3.9="708 ГУК" p3.10="Начертательная геометрия и компьютерная графика" pk3.10="НГиКГ" 
        s3.10="Курманалиева Ш. М." a3.10="708 ГУК" p3.11="-" pk3.11="-" s3.11="" a3.11="-" p3.12="-" 
        pk3.12="-" s3.12="" a3.12="-"></day1>
        </day1>
    </root>

And my not working Code:

@IBOutlet weak var tableView: UITableView!

func parser = NSXMLParser()
var schedule = NSDictionary()
var elements = NSMutableDictionary()
var element = NSString()

func beginParsing()
{
   parser = NSXMLParser(contentsOfURL: NSURL(string: "SomeUrl")!)! 
   parser.delegate = self
   parser.parse()
}

func parser(parser: NSXMLParser!, didStartElement elementName: String!, namespaceURI: String!, qualifiedName qName: String!, attributes attributeDict: [NSObject : AnyObject]!)
{
   element = elementName
   if (elementName as NSString).isEqualToString("day1")
   {
       //name of subject
       schedule = [p1.1="-", pk1.1="", s1.1="", a1.1="", p1.2="", pk1.2="",
       s1.2="", a1.2="", p1.3="",  pk1.3="", s1.3="", 
       a1.3="", p1.4="", pk1.4="", 
       s1.4="", a1.4="", p1.5="", pk1.5="", s1.5="", 
       a1.5="", p1.6="", pk1.6="", s1.6="", a1.6="", 
       p1.7="", pk1.7="", s1.7="", a1.7="", p1.8="", 
       pk1.8="", s1.8="", a1.8="", p1.9="", 
       pk1.9="", s1.9="", a1.9="", p1.10="", pk1.10="", 
       s1.10="", a1.10=""]

       elements = NSMutableDictionary()
       elements = [:]

  }
}

func parser(parser: NSXMLParser!, foundCharacters string: NSString!)
{
   if element.isEqualToString("day1") {
   func parser(parser: NSXMLParser!, didStartElement elementName: String!, namespaceURI: String!, qualifiedName: String!, attributes: [NSObject : AnyObject]!) {

           element = elementName
           if (elementName as NSString).isEqual("day1") {

           }
       }
   }
} 


func parser(parser: NSXMLParser!, didEndElement elementName: String!, namespaceURI: String!, qualifiedName qName: String!)
{
   if (elementName as NSString).isEqualToString("day1") {
      print(schedule)
   }`

And i don't create this XML data, this XML data give me my university

Upvotes: 1

Views: 3276

Answers (2)

Anand Nimje
Anand Nimje

Reputation: 6251

Use this class for Parse XML data with the help of SWXMLHash xml parser in Swift language.

https://github.com/drmohundro/SWXMLHash


import UIKit

public struct ParseMyXMLApis {

    //MARK:- Parsing API here
    public static func getparseMyApi(input: String, action:String, completion: (result: String, error: NSError?) -> Void) {

        //Main API here
        let is_URL: String = "Enter your url here"

        let lobj_Request = NSMutableURLRequest(URL: NSURL(string: is_URL)!)
        let session = NSURLSession.sharedSession()

        lobj_Request.HTTPMethod = "POST"
        lobj_Request.HTTPBody = input.dataUsingEncoding(NSUTF8StringEncoding)
        //lobj_Request.addValue("www.cgsapi.com", forHTTPHeaderField: "Host")
        lobj_Request.addValue("text/xml; charset=utf-8", forHTTPHeaderField: "Content-Type")
        lobj_Request.addValue(String(input.characters.count), forHTTPHeaderField: "Content-Length")
        lobj_Request.addValue("http://tempuri.org/IService/\(action)", forHTTPHeaderField: "SOAPAction")

        let task = session.dataTaskWithRequest(lobj_Request, completionHandler: {(data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in
            print("Response: \(response)")

            // Checking here Response
        if response != nil {

            let statusCode = (response as! NSHTTPURLResponse).statusCode
            print("Success: \(statusCode)")

            // Checking here Response Status
        if statusCode == 200 {
            //Handling Data here
            if data?.length > 0 {
            let strData = NSString(data: data!, encoding: NSUTF8StringEncoding)
            let xmls = SWXMLHash.parse(data!)
            func enumerate(indexer: XMLIndexer, level: Int) {
                for child in indexer.children {
                    let name:String? = child.element!.name
                    print("\(level) \(name)")
                    let text = child.element!.text
                    if text?.isEmpty == false{
                        print(text)
                        // Finish here Process
                        completion(result: text!, error: nil)
                    }
                    enumerate(child, level: level + 1)
                }

             }
             enumerate(xmls, level: 0)

            }else{
                //Data nil Condition here
                completion(result:"", error:error)
            }

            //Handling Error here
            if error != nil
            {
                print("Error: " + error!.description)
                completion(result:"", error:error)
            }

          }else{
                //Invalid Status
                print("Error: " + error!.description)
                completion(result:"", error:error)
            }

         }else{
            //Response Nil then handle here
            print("Error: " + error!.description)
            completion(result:"", error:error)
         }

        })
        task.resume()
    }

    //MARK:- String To Dictionary Conversion
    public func convertStringToDictionary(text: String) -> AnyObject! {
        if let data = text.dataUsingEncoding(NSUTF8StringEncoding) {
            do{
                let json:AnyObject = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions(rawValue: 0))
                return json
            }catch{
                print(error)
            }
        }
        return nil
    }

}

and Call this class

ParseMyXMLApis.getparseMyApi("Request here", action:"URL here", completion: { (result, error) -> Void in
                if error != nil{
                    //Handel Error here
                           }else{
                    print("Result is here\(result)")
                     }
        else
        {
            //Network Error Handling here
            print("Couldn't connect to network")
             }
      }

Upvotes: 0

Rob
Rob

Reputation: 437432

A couple of observations:

  1. Your didStartElement should simply look at attributeDict to get the attributes for an element.

  2. You don't need a foundCharacters method in this case, because you're only parsing elements tags, and not parsing anything between the open and close tags.

  3. The foundCharacters method, if you even needed it, shouldn't have a private didStartElement implemented within it.

  4. The only trick in your example is that you have very confusing XML with nested day1 tags. I'd really suggest changing the XML to something that makes sense.

    But, if you're stuck with this, one fairly flexible solution is to keep a stack of element names (implemented as simple array, elementNames), push an elementName onto the stack in didStartElement (by adding to the end of the array of elementNames) and popping one off in didEndElement (by calling removeLast). So, for example, by the time you hit the inner day1 tag inside your XML, the array of elementNames will be ["root", "day1", "day1"].

    Now that you have that, you can check to see if you are looking at day1 inside another day1 by seeing if the last two items in elementNames are both day1.

For example:

func beginParsing(URL: NSURL) {
    let parser = NSXMLParser(contentsOfURL: URL)!
    parser.delegate = self
    parser.parse()
    print(schedule)
}

var schedule: [String: String]?
var elementNames = [String]()

func parser(parser: NSXMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {
    elementNames.append(elementName)
    let count = elementNames.count

    if count >= 2 && elementNames[count - 2] == "day1" && elementNames[count - 1] == "day1" {
        schedule = attributeDict
    }
}

func parser(parser: NSXMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
    elementNames.removeLast()
}

func parser(parser: NSXMLParser, parseErrorOccurred parseError: NSError) {
    print(parseError)
}

Upvotes: 3

Related Questions