drmohundro/SWXMLHash 和 Swift 中的转义值

drmohundro/SWXMLHash and escaping values in Swift

我正在处理一个处理 xml 响应的项目​​。经过搜索,我在 github drmohundro/SWXMLHash 上找到了一个库,它的工作灵感来自 "Swifty JSON"。使用一段时间后,我意识到我无法通过转义值获取值。

xml 响应看起来像

let xmlResponseString = "<TrackList><Entry><Id>2</Id><Uri>/Input/E21u</Uri><Metadata><DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/"><item id="E21"><dc:title>Doing It To Death</dc:title><upnp:album>Ash & Ice</upnp:album><upnp:artist>The Kills</upnp:artist><upnp:class>object.item.audioItem.musicTrack</upnp:class><upnp:albumArtURI>http://192.168.1.106:8088/storage/emulated/0/record_cache/album_art/1535461905688.jpg</upnp:albumArtURI><res sampleFrequency="96000" bitsPerSample="24" bitrate="2304000" nrAudioChannels="2" protocolInfo="http-get:*:audio/mpeg" duration="00:04:07.431">/Input/E21</res></item></DIDL-Lite></Metadata></Entry></TrackList>"

在响应中专辑名称等于 "Ash & Ice"。但是返回的值是 "Ash "

这就是我获取值的方式:

let xmlHash = SWXMLHash.parse(xmlResponseString)
albumName = xmlHash["DIDL-Lite"]["item"]["upnp:album"].element?.text

此外,检查 "xmlHash" 看起来错误已经来自 "SWXMLHash.parse(xmlResponseString)"。

"xmlResponseString" 是否需要转义? 这是图书馆没有正确处理的事情吗? 还有其他选择吗?

谢谢

编辑 响应来自另一个 OpenHome 提供商设备。

原回复是:

<TrackList>
<Entry>
    <Id>2</Id>
    <Uri>/Input/E21u</Uri>
    <Metadata>&#60;DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/"&#62;&#60;item id="E21"&#62;&#60;dc:title&#62;Doing It To Death&#60;/dc:title&#62;&#60;upnp:album&#62;Ash &#38; Ice&#60;/upnp:album&#62;&#60;upnp:artist&#62;The Kills&#60;/upnp:artist&#62;&#60;upnp:class&#62;object.item.audioItem.musicTrack&#60;/upnp:class&#62;&#60;upnp:albumArtURI&#62;http://192.168.1.106:8088/storage/emulated/0/record_cache/album_art/1535461905688.jpg&#60;/upnp:albumArtURI&#62;&#60;res sampleFrequency="96000" bitsPerSample="24" bitrate="2304000" nrAudioChannels="2" protocolInfo="http-get:*:audio/mpeg" duration="00:04:07.431"&#62;/Input/E21&#60;/res&#62;&#60;/item&#62;&#60;/DIDL-Lite&#62;
    </Metadata>
</Entry>

根据开发人员的说法,元数据值已被转义,因为它是 XML 内的 XML。不确定这是否重要

因为我想创建一个通用的解析函数来填充 class,所以我创建了这个方法:

func unescapeXMLPredefinedCharacters(value:String?) -> String{

var audioString = ""

if value != nil{

    audioString = value!

    //Replace Unicode HTML Entity
    audioString = audioString.replacingOccurrences(of: "&quot;", with: "\"")
    audioString = audioString.replacingOccurrences(of: "&amp;", with: "&")
    audioString = audioString.replacingOccurrences(of: "&apos;", with: "'")
    audioString = audioString.replacingOccurrences(of: "&lt;", with: "<")
    audioString = audioString.replacingOccurrences(of: "&gt;", with: ">")


    //Replace Unicode Decimal
    audioString = audioString.replacingOccurrences(of: "&#34;", with: "\"")

    audioString = audioString.replacingOccurrences(of: "&#38;", with: "&")
    audioString = audioString.replacingOccurrences(of: "&#39;", with: "'")
    audioString = audioString.replacingOccurrences(of: "&#60;", with: "<")
    audioString = audioString.replacingOccurrences(of: "&#62;", with: ">")


    //Replace Unicode Hex
    audioString = audioString.replacingOccurrences(of: "&#x22;", with: "\"")
    audioString = audioString.replacingOccurrences(of: "&#x26;", with: "&")
    audioString = audioString.replacingOccurrences(of: "&#x27;", with: "'")
    audioString = audioString.replacingOccurrences(of: "&#x3c;", with: "<")
    audioString = audioString.replacingOccurrences(of: "&#x3e;", with: ">")

}

return audioString

}

它不知道使用了哪种 unicode 类型进行反转义。

然后我从我原来的问题中得到答案

问题是 escaped 内部 xml 在某种意义上已经是错误的,它包含 & 个字符(在 unicode 中),也许 < 和其他人。

首先,您应该 unescape unicode 实体,例如&amp;&lt;,因为XmlParser 会为您处理。

然后,您应该将 &#38; 等 unicode 实体转义为 xml 实体,例如 &amp;(而不是 &),然后 xml 解析器将处理(见上文)

根据Andreas Answer,我改变了函数

func unescapeXMLPredefinedCharacters(value:String?) -> String{

    var audioString = ""

    if value != nil{

        audioString = value!

        //Replace Unicode Decimal
        audioString = audioString.replacingOccurrences(of: "&#34;", with: "&quot;")
        audioString = audioString.replacingOccurrences(of: "&#38;", with: "&amp;")
        audioString = audioString.replacingOccurrences(of: "&#39;", with: "&apos;")
        audioString = audioString.replacingOccurrences(of: "&#60;", with: "&lt;")
        audioString = audioString.replacingOccurrences(of: "&#62;", with: "&gt;")

    }

    return audioString

}