Разбор XML с SwiftyXMLParser Alamofire - PullRequest
0 голосов
/ 01 февраля 2020

Я пытаюсь проанализировать последний элемент, полученный от API веб-сервера, в формате XML, но я совершенно не понимаю, как получить данные для sky_condition (не слишком много объяснений по поводу использования сервера, по-видимому, не является вектором)

Как видно из древовидного представления ниже, я могу получить все примеры данных прогноза, fcst_time_from или wind_dir_degrees

Tree View of the XML

с использованием следующего кода (я замкнул код, весь этот код находится внутри запроса Alamo, в течение для l oop, чтобы получить весь прогноз для определенного аэропорта c, может быть больше чем один)

let winddirdegrees = parsedData.response.data.TAF.forecast[index].wind_dir_degrees.int

но, когда я пытаюсь получить sky_condition, это действительно работает.

let skycondition = parsedData.response.data.TAF.forecast[index].sky_condition.sky_cover.text

Я публикую здесь xml код этой части: и ССЫЛКА с полной XML ссылкой XML

</forecast>
      <forecast>
        <fcst_time_from>2020-02-02T03:00:00Z</fcst_time_from>
        <fcst_time_to>2020-02-02T05:00:00Z</fcst_time_to>
        <change_indicator>BECMG</change_indicator>
        <time_becoming>2020-02-02T04:00:00Z</time_becoming>
        <wind_dir_degrees>260</wind_dir_degrees>
        <wind_speed_kt>6</wind_speed_kt>
        <visibility_statute_mi>3.73</visibility_statute_mi>
        <wx_string>NSW</wx_string>
        <sky_condition sky_cover="FEW" cloud_base_ft_agl="3500" />
      </forecast>

к сожалению, сайт не дает большого объяснения относительно этого они просто показывают это xml в объяснении

<xsd:element name="sky_condition">
        <xsd:complexType>
            <xsd:attribute name="sky_cover" type="xsd:string"/>
            <xsd:attribute name="cloud_base_ft_agl" type="xsd:int"/>
            <xsd:attribute name="cloud_type" type="xsd:string"/> 
        </xsd:complexType>
    </xsd:element>

заранее спасибо за помощь.

1 Ответ

0 голосов
/ 01 февраля 2020

Это может помочь вам,

fileprivate class XmlToDictionaryParserDelegate: NSObject, XMLParserDelegate {

    private var currentElement: XmlElement?

    fileprivate init(_ element: XmlElement) {
        self.currentElement = element
    }

    public func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
        self.currentElement = self.currentElement?.pop(elementName)
    }

    public func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {
        self.currentElement = self.currentElement?.push(elementName)
        self.currentElement?.attributeDict = attributeDict
    }

    func parser(_ parser: XMLParser, foundCharacters string: String) {
        self.currentElement?.text += string
    }
}

public class XmlElement {
    public private(set) var name = "unnamed"
    public private(set) var children = [String: XmlElement]()
    public private(set) var parent: XmlElement? = nil
    public fileprivate(set) var text = ""
    public fileprivate(set) var attributeDict: [String : String] = [:]

    private init(_ parent: XmlElement? = nil, name: String = "") {
        self.parent = parent
        self.name = name
    }

    public convenience init?(fromString: String) {
        guard let data = fromString.data(using: .utf8) else {
            return nil
        }
        self.init(fromData: data)
    }

    public init(fromData: Data) {
        let parser = XMLParser(data: fromData)
        let delegate = XmlToDictionaryParserDelegate(self)
        parser.delegate = delegate
        parser.parse()
    }

    fileprivate func push(_ elementName: String) -> XmlElement {
        let childElement = XmlElement(self, name: elementName)
        children[elementName] = childElement
        return childElement
    }

    fileprivate func pop(_ elementName: String) -> XmlElement? {
        assert(elementName == self.name)
        return self.parent
    }

    public subscript(name: String) -> XmlElement? {
        return self.children[name]
    }
}

И вы можете использовать, как показано ниже,

let url = URL(string: "APIURL")
    var xmlRequest = URLRequest(url: url!)
    xmlRequest.httpBody = stringParams.data(using: String.Encoding.utf8, allowLossyConversion: true)
    xmlRequest.httpMethod = "POST"
    xmlRequest.addValue("application/xml", forHTTPHeaderField: "Content-Type")
    Alamofire.request(xmlRequest)
        .responseData { (response) in
            guard let jsonData = response.data, let stringResponse: String = String(data: jsonData, encoding: String.Encoding.utf8) else {return}
            guard let xml = XmlElement(fromString: stringResponse) else { return }
            let status = xml["sky_condition"]?.text
    }
...