drmohundro / SWXMLHash и экранирование значений в Swift - PullRequest
0 голосов
/ 29 августа 2018

Я работаю над проектом, который обрабатывает ответы 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". Однако возвращаемое значение равно «Ясень»

Вот так я получаю значение:

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

Кроме того, проверка «xmlHash» выглядит так, как будто ошибка уже произошла из «SWXMLHash.parse (xmlResponseString)».

Нужно ли экранировать xmlResponseString? Это то, что библиотека не обрабатывает должным образом? Любая альтернатива?

Спасибо

EDIT Ответ приходит от другого устройства поставщика 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. Не уверен, если это имеет значение

Поскольку я хочу создать универсальную функцию разбора для заполнения класса, я создал этот метод:

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

}

Он не знает, какой тип юникода использовался для эскапинга.

Тогда я получаю ответ от моего первоначального вопроса

Ответы [ 2 ]

0 голосов
/ 29 августа 2018

Согласно Андреасу Ответу, я изменил функцию

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

}
0 голосов
/ 29 августа 2018

Проблема в том, что экранированный внутренний xml уже неверен в том смысле, что он содержит & символов (в юникоде), а может быть < и других.

Во-первых, вы должны не исключать юникодные сущности типа &amp; или &lt; вообще, потому что XmlParser обрабатывает это для вас.

Затем вы должны удалить unicode-сущности, такие как &#38; и т. Д., В xml-сущности, такие как &amp; (вместо &), которые затем будет обрабатывать синтаксический анализатор xml (см. Выше)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...