4

I am new in IOS and i want convert some mix data(xml and JSON mix data ) receive from SOAP web service into array using swift 3. i receive this data in a string variable in parser method.

func connection(_ connection: NSURLConnection, didFailWithError error: Error){
    print("\(error)")
    print("Some error in your Connection. Please try again.")
    let alert = UIAlertController(title: "Error", message: "No internet connection", preferredStyle: UIAlertControllerStyle.alert)

    // add an action (button)
    alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))

    self.present(alert, animated: true, completion: nil)
}

func connectionDidFinishLoading(_ connection: NSURLConnection){

    print("Received \(UInt(webResponseData.count)) Bytes")
    // let theXML = String(webResponseData.mutableBytes, length: webResponseData.length, encoding: String.Encoding.utf8)
    let theXML =  XMLParser(data: webResponseData)
    theXML.delegate = self
    theXML.parse()
    print("\(theXML)")
}

func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String, qualifiedName qName: String, attributes attributeDict: [AnyHashable: Any]){
    currentElement = elementName
   // print(currentElement)
}

func parser(_ parser: XMLParser, foundCharacters string: String){

   currentElement = string
    UserDefaults.standard.set(currentElement, forKey: "string")

    //print(currentElement)
   // arr.append(currentElement)
}

func parser(_ parser: XMLParser,didEndElement elementName: String, namespaceURI: String?,qualifiedName qName: String?){

    let sessionelement = UserDefaults.standard.object(forKey: "string")
    print(sessionelement!)
}

here is response from from web service:

[{"Id":2,"imgName":"_U11tmp1464839741959976567.jpg","SeqNo":1},
{"Id":1,"imgName":"_U11tmp1464839741959976567.jpg","SeqNo":2},
{"Id":3,"imgName":"_U11tmpIMG-14117-WA59976567.jpg","SeqNo":3}]
5
  • 2
    The response in your question is a pure JSON response, where is the XML part? And what is your question, it seems like you are already doing the parsing? Commented Aug 10, 2017 at 9:26
  • ok sir got it.I want to store this data in different array.like id in one array and imageName in other array Commented Aug 10, 2017 at 9:57
  • how to retrieve from this response to array? Commented Aug 10, 2017 at 9:57
  • Check out my answer. You didn't tell me what type the variables has in which the JSON response is stored, so I made an assumption, tell me if it's something else and i will update my answer. Commented Aug 10, 2017 at 10:04
  • jason response stored in String variable....variable is currentElement Commented Aug 10, 2017 at 10:22

2 Answers 2

10

With the help of below code block, you can convert any of complex XML to JSON. I am converting XML of 50 pages and it works like charm. Once you get json, you can directly map it to your model class.

import Foundation
class ParseXMLData: NSObject, XMLParserDelegate {

var parser: XMLParser
var elementArr = [String]()
var arrayElementArr = [String]()
var str = "{"

init(xml: String) {
    parser = XMLParser(data: xml.replaceAnd().replaceAposWithApos().data(using: String.Encoding.utf8)!)
    super.init()
    parser.delegate = self
}

func parseXML() -> String {
    parser.parse()

    // Do all below steps serially otherwise it may lead to wrong result
    for i in self.elementArr{
        if str.contains("\(i)@},\"\(i)\":"){
            if !self.arrayElementArr.contains(i){
                self.arrayElementArr.append(i)
            }
        }
        str = str.replacingOccurrences(of: "\(i)@},\"\(i)\":", with: "},") //"\(element)@},\"\(element)\":"
    }

    for i in self.arrayElementArr{
        str = str.replacingOccurrences(of: "\"\(i)\":", with: "\"\(i)\":[") //"\"\(arrayElement)\":}"
    }

    for i in self.arrayElementArr{
        str = str.replacingOccurrences(of: "\(i)@}", with: "\(i)@}]") //"\(arrayElement)@}"
    }

    for i in self.elementArr{
        str = str.replacingOccurrences(of: "\(i)@", with: "") //"\(element)@"
    }

    // For most complex xml (You can ommit this step for simple xml data)
    self.str = self.str.removeNewLine()
    self.str = self.str.replacingOccurrences(of: ":[\\s]?\"[\\s]+?\"#", with: ":{", options: .regularExpression, range: nil)

    return self.str.replacingOccurrences(of: "\\", with: "").appending("}")
}

// MARK: XML Parser Delegate
func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {

    //print("\n Start elementName: ",elementName)

    if !self.elementArr.contains(elementName){
        self.elementArr.append(elementName)
    }

    if self.str.last == "\""{
        self.str = "\(self.str),"
    }

    if self.str.last == "}"{
        self.str = "\(self.str),"
    }

    self.str = "\(self.str)\"\(elementName)\":{"

    var attributeCount = attributeDict.count
    for (k,v) in attributeDict{
        //print("key: ",k,"value: ",v)
        attributeCount = attributeCount - 1
        let comma = attributeCount > 0 ? "," : ""
        self.str = "\(self.str)\"_\(k)\":\"\(v)\"\(comma)" // add _ for key to differentiate with attribute key type
    }
}

func parser(_ parser: XMLParser, foundCharacters string: String) {
    if self.str.last == "{"{
        self.str.removeLast()
        self.str = "\(self.str)\"\(string)\"#" // insert pattern # to detect found characters added
    }
}

func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {

    //print("\n End elementName \n",elementName)
    if self.str.last == "#"{ // Detect pattern #
        self.str.removeLast()
    }else{
        self.str = "\(self.str)\(elementName)@}"
    }
}
}

Add String extension

extension String{
    // remove amp; from string
func removeAMPSemicolon() -> String{
    return replacingOccurrences(of: "amp;", with: "")
}

// replace "&" with "And" from string
func replaceAnd() -> String{
    return replacingOccurrences(of: "&", with: "And")
}

// replace "\n" with "" from string
func removeNewLine() -> String{
    return replacingOccurrences(of: "\n", with: "")
}

func replaceAposWithApos() -> String{
    return replacingOccurrences(of: "Andapos;", with: "'")
}
}

Make a call from your class

let xmlStr = "<Your XML string>"
let parser = ParseXMLData(xml: xmlStr)
let jsonStr = parser.parseXML()
print(jsonStr)

I hope this may help you.

Sign up to request clarification or add additional context in comments.

Comments

1

This is a working example, I have tested it in a playground. You need to convert your JSON String to a Data object first, then parse it.

let jsonString = "[{\"Id\":2,\"imgName\":\"_U11tmp1464839741959976567.jpg\",\"SeqNo\":1},{\"Id\":1,\"imgName\":\"_U11tmp1464839741959976567.jpg\",\"SeqNo\":2},{\"Id\":3,\"imgName\":\"_U11tmpIMG-14117-WA59976567.jpg\",\"SeqNo\":3}]"
guard let jsonData = jsonString.data(using: .utf8) else {return}
guard let jsonResponse = (try? JSONSerialization.jsonObject(with: jsonData)) as? [[String:Any]] else {return}
let idArray = jsonResponse.flatMap{$0["Id"] as? Int}
let imageNames = jsonResponse.flatMap{$0["imgName"] as? String}

To put this into context of your code:

func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String, qualifiedName qName: String, attributes attributeDict: [AnyHashable: Any]){
    currentElement = elementName
    guard let jsonData = currentElement.data(using: .utf8) else {return}
    guard let jsonResponse = (try? JSONSerialization.jsonObject(with: jsonData)) as? [[String:Any]] else {return}
    let idArray = jsonResponse.flatMap{$0["Id"] as? Int}
    let imageNames = jsonResponse.flatMap{$0["imgName"] as? String}
}

4 Comments

i have checked it but it will gives error when i use this let idArray = jsonResponse.flatMap{$0["Id"]}
i am using my response not this code for response guard let jsonResponse = (try? JSONSerialization.jsonObject(from: data)) as? [[String:Any]] else {return}
Check my updated answer. The problem was that your JSON was stored in a String.
Glad I could help @rachnasharma . If you found my answer helpful, please consider accepting it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.