Search code examples
xmlswiftswift2swxmlhash

Can't return value parsing XML using SWXMLHash in Swift


When I try to show "50%", which is taken from

forecast > area > forecast-period > text > probability_of_precipitation

it comes up with "nil" on my label in the storyboard.

I have this snippet of XML, which is located at a public ftp address (shown in my code below)

<forecast>
        <area aac="VIC_FA001" description="Victoria" type="region"/>
        <area aac="VIC_PW001" description="Mallee" type="public-district" parent-aac="VIC_FA001"/>
        <area aac="VIC_PT043" description="Mildura" type="location" parent-aac="VIC_PW001">
            <forecast-period index="0" start-time-local="12pm" end-time-local="12:30pm" start-time-utc="1:00pm" end-time-utc="1:30pm">
                <element type="forecast_icon_code">16</element>
                <text type="precis">Shower or two. Possible storm.</text>
                <text type="probability_of_precipitation">50%</text>
            </forecast-period>
        </area>
</forecast>

And here is my code:

let urlStringMax = "ftp://ftp2.bom.gov.au/anon/gen/fwo/IDV10753.xml"

    if let urlMax = NSURL(string: urlStringMax)
    {
        if let data = try? NSData(contentsOfURL: urlMax, options: [])
        {
            let xml = SWXMLHash.parse(data)

            let precipForecast = xml["forecast"]["area"][2]["forecast-period"][0]["text"][type="probability_of_precipitation"].element?.text

            maxTemp.text = "\(precipForecast)"
        }
    }

Solution

  • Firt thing: you forgot to include ["product"] at the beginning of your query.

    Then your last subscripting with [type="probability_of_precipitation"] wasn't using the right syntax.

    Here's two different ways of getting your value.

    1- By index:

    let precipForecast = xml["product"]["forecast"]["area"][2]["forecast-period"][0]["text"][1].element?.text
    

    2- By attributes, with .withAttr. In your case, for "type":

    do {
        let precipForecast = try xml["product"]["forecast"]["area"][2]["forecast-period"][0]["text"].withAttr("type", "probability_of_precipitation").element?.text
    } catch {
        print(error)
    }
    

    or if your want an Optional:

    let precipForecast = try? xml["product"]["forecast"]["area"][2]["forecast-period"][0]["text"].withAttr("type", "probability_of_precipitation").element?.text