0

I am trying to do XML Parsing of below file :

<bgmusic>
  <genre title=“Title1”>
    <track title=“SubTitle1” path="https://test/Background_Track%20-%20Ambient%20-%20ANW2856_01_ Animation.ogg" />
    <track title="SubTitle2” path="https://test/Background_Track%20-%20Ambient%20-%20ANW2860_02_Entanglement.ogg" />
  </genre>

  <genre title="Title2”>
    <track title="SubTitle3” path="https://test/Background_Track%20-%20Ambient%20-%20ANW2856_01_Animate.ogg" />
    <track title="SubTitle4” path="https://test/Background_Track%20-%20Ambient%20-%20ANW2860_02_ SubTitle4.ogg" />
  </genre>

</bgmusic>

Basically I have created two ViewController, one for displaying Genre Title and second VC for displaying the details of this. For this, I have created below two Modal classes:

class GenreModel {
    var title: String = ""

    var genreSongsArray = [GenreSong]()
    var genreSongs = GenreSong()
}

class GenreSong {
    var songTitle: String = ""
    var path: String = ""

}

Here is my code:

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

       let genreModel = GenreModel()

        if(elementName == "genre"){

        if let id = attributeDict["title"] {
            genreModel.title = id
        }
       }

        if(elementName == "track")
        {
            let genreSong = GenreSong()
            for string in attributeDict {
                let strvalue = string.value as NSString
                switch string.key {
                case "title":
                    genreSong.songTitle = strvalue as String
                    break
                case "path":
                    genreSong.path = strvalue as String
                    break

                default:
                    break
                }
            }

            genreModel.genreSongsArray.append(genreSong)
        }
}

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

    }

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

    }

My problem is when I am giving "elementName == genre" then it's only parsing genre title and not parsing track details. How can I save both Genre title and Songs details in one custom Array?

Can anyone please suggest me on this? Thank you!

6
  • In what class are you implementing XMLParserDelegate? You need to keep the results (see your let genreModel = GenreModel(), it's a local variable and can never accessed again one the methods is finished) inside the class. Commented Sep 20, 2018 at 6:49
  • I am using XMLParserDelegate in my first VC where I an display a list of Genre titles. Yeah I understand what you are telling me. But I have created my custom array globally, so can get both title and genre song details using that array. Commented Sep 20, 2018 at 6:51
  • The problem is parsing this and save both title and genre song details in my custom array index wise. Commented Sep 20, 2018 at 6:52
  • I you have really understand what I said, you should have shown more code. Commented Sep 20, 2018 at 6:54
  • Globally I have declared "var genreDataSource = [GenreModel]()" and trying to parse both datas and append into this. Commented Sep 20, 2018 at 6:56

1 Answer 1

0

You need to rethink your parsing strategy.

The XMLParser fires didStartElement whenever a new element starts. So the first occurence is on the "genre" element.

The next two elements are "track" so the parser again fires didStartElement for each of them.

It is your responsibility to keep track of the hierarchy so you need to store the current element in a variable and process the subelements.

So whenever you retrieve a new element with didStartElement you have to check what element it is and what child elements you expect further. This all depends on the structure of your XML document so there is no all in one solution one can give you.

...
var genre = ""
var tracks = [String]()

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

    if(elementName == "genre") {
        // new genre
        tracks = []

        if let id = attributeDict["title"] {
            genre = id
        }
     }

     if(elementName == "track") {
        // new subElement track, add it to the tracks array here
     }
}

func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
    if(elementName == "genre") {
        // genre complete with all tracks, process it
    }
}
Sign up to request clarification or add additional context in comments.

8 Comments

Thanks for your suggestion @zisoft, I am not getting any idea to track the hierarchy. I can't able to fetch the track details using start element genre here.
And also my XML data is dynamic, there can be multiple tracks for a title.
@AnandGautam I have added some pseudo code. Hope you get the idea.
Thanks for your answer, but when we will parse in this way. And when I will append my global custom array in didStartElement, so for the 0 index of array I can save only title and for the first index I can save only track details. But I want to save both data into 0 index of my array.
I have not created separate separate array for title and track details.
|

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.