如何用SWXMLHash反序列化嵌套XML?chargingdevice节点值缺失
解决SWXMLHash反序列化时遗漏多个同名XML节点的问题
你当前的问题是使用SWXMLHash反序列化XML时,只获取到第一个chargingdevice节点的值,第二个同名节点被遗漏了。
原XML片段
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:xal="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0" xmlns:atom="http://www.w3.org/2005/Atom"> <Document> <name>Stations</name> <Style id="AVAILABLE"> <IconStyle> <scale>1.0</scale> <heading>0.0</heading> <Icon> <href>http://maps.google.com/mapfiles/kml/paddle/grn-circle.png</href> <refreshInterval>0.0</refreshInterval> <viewRefreshTime>0.0</viewRefreshTime> <viewBoundScale>0.0</viewBoundScale> </Icon> </IconStyle> </Style> <Style id="UNAVAILABLE"> <IconStyle> <scale>1.0</scale> <heading>0.0</heading> <Icon> <href>http://maps.google.com/mapfiles/kml/paddle/red-circle.png</href> <refreshInterval>0.0</refreshInterval> <viewRefreshTime>0.0</viewRefreshTime> <viewBoundScale>0.0</viewBoundScale> </Icon> </IconStyle> </Style> <Placemark> <name>Esch-sur-Alzette - Parking souterrain Brill - Place de la Résistance</name> <visibility>1</visibility> <address>Rue Louis Pasteur, L-4276 Esch-sur-Alzette Luxembourg</address> <description><span><b>4</b> connectors with 22kW and Type 2 connector<span><br/><span><b>4</b> available connectors<span><br/><span><b>0</b> occupied connectors<span><br/></description> <styleUrl>#AVAILABLE</styleUrl> <ExtendedData> <Data name="CPnum"> <displayName>Number of chargingpoints</displayName> <value>4</value> </Data> <Data name="chargingdevice"> <displayName>Charging device</displayName> <value>{"id":10644,"name":"CP2500","numberOfConnectors":2,"connectors":[{"id":59985,"name":"CP2500 - 1","maxchspeed":22.08,"connector":1,"description":"AVAILABLE"},{"id":59986,"name":"CP2500 - 2","maxchspeed":22.08,"connector":2,"description":"AVAILABLE"}]}</value> </Data> <Data name="chargingdevice"> <displayName>Charging device</displayName> <value>{"id":10645,"name":"CP2501","numberOfConnectors":2,"connectors":[{"id":59987,"name":"CP2501 - 1","maxchspeed":22.08,"connector":1,"description":"AVAILABLE"},{"id":59988,"name":"CP2501 - 2","maxchspeed":22.08,"connector":2,"description":"AVAILABLE"}]}</value> </Data> </ExtendedData> <Point> <altitudeMode>clampToGround</altitudeMode> <coordinates>5.97622,49.492728</coordinates> </Point> </Placemark> </Document> </kml>
原Swift代码
struct XMLPlacemark: XMLObjectDeserialization { var name: String var visibility: Int var address: String var description: String var styleUrl: String var cpnumber : Int var chargingdevice : [String] static func deserialize(_ node: XMLIndexer) throws -> XMLPlacemark { return try XMLPlacemark( name: node["name"].value(), visibility: node["visibility"].value(), address: node["address"].value(), description: node["description"].value(), styleUrl: node["styleUrl"].value(), cpnumber: node["ExtendedData"]["Data"].withAttribute("name", "CPnum")["value"].value(), chargingdevice: node["ExtendedData"]["Data"].withAttribute("name","chargingdevice")["value"].value() ) } } func loadtest() { let xml = XMLHash.parse(stationXML) if let station: [XMLPlacemark] = try? xml["kml"]["Document"]["Placemark"].value() { station.forEach {station in print("\(station.chargingdevice)") } } }
当前问题结果
仅获取到第一个chargingdevice的值:
["{\"id\":10644,\"name\":\"CP2500\",\"numberOfConnectors\":2,\"connectors\":[{\"id\":59985,\"name\":\"CP2500 - 1\",\"maxchspeed\":22.08,\"connector\":1,\"description\":\"AVAILABLE\"},{\"id\":59986,\"name\":\"CP2500 - 2\",\"maxchspeed\":22.08,\"connector\":2,\"description\":\"AVAILABLE\"}]}"]
解决方案
问题出在withAttribute方法默认仅返回第一个匹配属性条件的节点,要获取所有同名节点,需要遍历筛选所有符合条件的Data节点,再提取每个节点的value值。
修改XMLPlacemark的deserialize方法中chargingdevice的赋值代码:
chargingdevice: try node["ExtendedData"]["Data"] .filter { try $0.value(ofAttribute: "name") == "chargingdevice" } .map { try $0["value"].value() }
修改后的完整结构体代码:
struct XMLPlacemark: XMLObjectDeserialization { var name: String var visibility: Int var address: String var description: String var styleUrl: String var cpnumber : Int var chargingdevice : [String] static func deserialize(_ node: XMLIndexer) throws -> XMLPlacemark { return try XMLPlacemark( name: node["name"].value(), visibility: node["visibility"].value(), address: node["address"].value(), description: node["description"].value(), styleUrl: node["styleUrl"].value(), cpnumber: node["ExtendedData"]["Data"].withAttribute("name", "CPnum")["value"].value(), chargingdevice: try node["ExtendedData"]["Data"] .filter { try $0.value(ofAttribute: "name") == "chargingdevice" } .map { try $0["value"].value() } ) } }
修改后重新运行,就能获取到两个chargingdevice节点的value值了。
内容的提问来源于stack exchange,提问作者Stee Ve
相关产品推荐
相关产品推荐

