0

I'm building a project for a train schedule app, and I'm using an API that returns an XML file,to manipulate the data i'm using the library called SWXMLHash.

I need to extract the name of the departure station with its destinations and departure times.

I created a class to store all these data, but I need to improve it because I'm having trouble extracting the destinations and departure times.

I was able to loop over the xml file and get the names of the departure stations.

Here is my class :

class Station {
  var name : String 
  var destinations:[(dest:String, times:[Int])] 

init(withName name: String, destinations:[(dest:String, times:[Int])]){
  self.name = name
  self.destinations = destinations

  }
}

Here is my code to extract the names of the stations :

// This code loops over the XML file and retrieves the name of the departure stations 

// create an empty array of Station class
var stationsTest = [Station]()

// retrieve the name of the departure stations and add them to and array of Station
for elem in xml["root"]["station"].all{
  var stations = elem["name"].element!.text!
  var stationPlaceHolder = Station(withName: stations, destinations: [(dest:"",times:[1])])
  stationsTest.append(stationPlaceHolder)
}

My problem is how can I get the destinations of each station with their appropriate times of departure

I suppose the problem is in the way I implemented my class, I need to find a better solution.

Here is a sample of the XML file that I'm working with:

<?xml version="1.0" encoding="utf-8"?><root><uri><!   [CDATA[http://api.bart.gov/api/etd.aspx?  cmd=etd&orig=ALL&ramdom=1454366707766]]></uri><date>02/01/2016</date>
<time>02:44:52 PM PST</time>
<station>
  <name>Lake Merritt</name>
  <abbr>LAKE</abbr>
  <etd>
    <destination>Daly City</destination>
    <abbreviation>DALY</abbreviation>
    <estimate>
      <minutes>3</minutes>
    </estimate>
    <estimate>
      <minutes>10</minutes>
    </estimate>
    <estimate>
      <minutes>17</minutes>
    </estimate>
  </etd>
  <etd>
    <destination>Dublin/Pleasanton</destination>
    <estimate>
      <minutes>7</minutes>
    </estimate>
    <estimate>
      <minutes>22</minutes>
    </estimate>
    <estimate>
      <minutes>37</minutes>
    </estimate>
  </etd>
  <etd>
    <destination>Fremont</destination>
    <estimate>
      <minutes>4</minutes>
    </estimate>
    <estimate>
      <minutes>14</minutes>
    </estimate>
    <estimate>
      <minutes>19</minutes>
    </estimate>
  </etd>
  <etd>
    <destination>Richmond</destination>
    <estimate>
      <minutes>5</minutes>
    </estimate>
    <estimate>
      <minutes>19</minutes>
    </estimate>
    <estimate>
      <minutes>34</minutes>
    </estimate>
  </etd>
</station>

<station>
  <name>Fruitvale</name>
  <etd>
    <destination>Daly City</destination>
    <estimate>
      <minutes>6</minutes>
    </estimate>
    <estimate>
      <minutes>12</minutes>
     </estimate>
    <estimate>
      <minutes>22</minutes>
    </estimate>
  </etd>
  <etd>
    <destination>Dublin/Pleasanton</destination>
    <estimate>
      <minutes>10</minutes>
    </estimate>
    <estimate>
      <minutes>25</minutes>
    </estimate>
    <estimate>
      <minutes>40</minutes>
    </estimate>
  </etd>
AziCode
  • 2,510
  • 6
  • 27
  • 53
  • 1
    You should be able to use an inner loop over `elem["ebd"].all` to gather the destinations for each station. – David Mohundro Feb 08 '16 at 15:14
  • @DavidMohundro could explain how would I do that ? I think the way I'm constructing my class "Station" is flawed. – AziCode Feb 17 '16 at 00:47
  • @DavidMohundro because each station has multiple destinations, and each destination has multiple times of arrival. an example of one station : `Berkeley[(destination1, times[1,2,3]), (destination2, times[4,5,6]),(destination3, times[7,8,9])]` – AziCode Feb 17 '16 at 00:57

1 Answers1

1

I used the below code in the SWXMLHash playground and it works on my machine:

// you need to model the ETD element as that has the destination and etd elements
class Etd {
    var destination: String = ""
    var estimates = [String]()

    init(destination: String, estimates: [String]) {
        self.destination = destination
        self.estimates = estimates
    }
}

// each station has a collection of ETDs (per the XML)
class Station {
    var name : String
    var etds = [Etd]()

    init(withName name: String, etds: [XMLIndexer]){
        self.name = name

        for etd in etds {
            self.etds.append(Etd(
                destination: etd["destination"].element!.text!,
                estimates: etd["estimate"].all.map { $0["minutes"].element!.text! })
            )
        }
    }
}

var stationsTest = [Station]()

for elem in xml["root"]["station"] {
    var stations = elem["name"].element!.text!
    var stationPlaceHolder = Station(withName: stations, etds: elem["etd"].all)
    stationsTest.append(stationPlaceHolder)
}

Basically, it looks like what you were missing was the abstraction for the Etd class - a station doesn't contain a list of destinations, but a list of Etds. Each Etd then has both a destination and estimates by minute.

David Mohundro
  • 11,922
  • 5
  • 40
  • 44
  • Thank you for your answer, but i'm a bit confused. I'm unable to use `àppendChild`in the for loop ```self.destinations.appendChild(dest["destination"].text!)``` and also each destination has a couple times associated with it – AziCode Feb 17 '16 at 22:44
  • Corrected, that should have been `append` - basically, loop them and add them to the array. For the times, you'll have to loop those as well, but you should be able to use the same approach that I'm suggesting for destinations. But first, just get destinations working. – David Mohundro Feb 17 '16 at 23:17
  • I'm having an ```error: cannot assign value of type '[XMLIndexer]' to type '[String]'``` – AziCode Feb 17 '16 at 23:19
  • I edited the answer - I'm not sure I can do more beyond the code snippet above. – David Mohundro Feb 18 '16 at 15:12
  • Thanks, I had the idea in mind but I couldn't implement it. Your help is much appreciated – AziCode Feb 18 '16 at 19:11