You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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>&lt;span&gt;&lt;b&gt;4&lt;/b&gt; connectors with 22kW and Type 2 connector&lt;span&gt;&lt;br/&gt;&lt;span&gt;&lt;b&gt;4&lt;/b&gt; available connectors&lt;span&gt;&lt;br/&gt;&lt;span&gt;&lt;b&gt;0&lt;/b&gt; occupied connectors&lt;span&gt;&lt;br/&gt;</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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 09:55:32