【问题标题】:parsing XML with SwiftyXMLParser Alamofire使用 SwiftyXMLParser Alamofire 解析 XML
【发布时间】:2020-02-01 09:36:05
【问题描述】:

我正在尝试以 XML 格式解析从 Web 服务器 API 收到的最后一项,但我完全不明白如何获取 sky_condition 的数据(关于服务器使用的解释不多,显然不是一个向量)

正如您在下面的树形视图中看到的那样,我可以获得所有预测数据示例,fcst_time_fromwind_dir_degrees

使用以下代码(我缩短了代码,所有这些代码都在 Alamo 请求中,在 for 循环中以获取特定机场的所有预报,可以不止一个)

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 的链接 Link 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>

提前感谢您的帮助。

【问题讨论】:

  • 我对 swift 的了解不够,无法自己尝试实现以下内容,因此无法将其发布为答案,但这可能会帮助您做到这一点:第一次和第二次尝试之间的区别是第一次你选择一个元素/节点的值(&lt;wind_dir_degrees&gt;),第二次你试图选择一个节点属性的属性值(&lt;sky_condition&gt;)。显然,您可以使用类似于if elementName == "sky_condition "{let clouds= attributeDict["cloud_base_ft_agl"]! as String...} 的函数。能够使用 xpath 会更容易。
  • 感谢您的评论我去检查了解析器的文档,并且有一个特殊的方法可以为属性做它。谢谢
  • 如果它对您有用,请将其作为答案发布,以供未来读者使用。

标签: swift xml parsing xml-parsing swifty-json


【解决方案1】:

这可能对你有帮助,

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
    }

【讨论】:

    猜你喜欢
    • 2017-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-02
    • 2018-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多