Почему мой код работает в Xcode Playground, но не в моем проекте? - PullRequest
0 голосов
/ 29 мая 2020

Я пытаюсь разобрать файл metadata.opf, который Caliber использует для управления электронными книгами с помощью Swift.

Мне удалось разобрать документ на игровой площадке:


import Foundation

class Metadata: CustomStringConvertible {

    var uuid = ""
    var title = ""
    var creators = [""]
    var serie = ""
    var serieIndex = 0

    var description: String { return
        "UUID: \(uuid)\nTitre: \(title)\nAuteur(s): \(creators)\nSérie: Tome \(serieIndex) de la série \(serie)"
    }

}

class OPFParser: NSObject {
    var xmlParser: XMLParser?
    var metadata: [Metadata] = []
    var xmlText = ""
    var currentMetadata: Metadata?
    var calibreAttributes: [String: String] = [:]
    var isUUID = false

    init(withXML xml: String) {
        if let data = xml.data(using: .utf8){
            xmlParser = XMLParser(data: data)
        }
    }

    func parse() -> [Metadata] {
        xmlParser?.delegate = self
        xmlParser?.parse()
        return metadata
    }
}

extension OPFParser: XMLParserDelegate {
    func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {
        xmlText = ""
        if elementName == "metadata" {
            currentMetadata = Metadata()
        }
        if elementName == "meta" {
            //print("\(attributeDict["content"]) : \(attributeDict["name"])")
            if attributeDict["name"] == "calibre:series" {
                if let serie = attributeDict["content"] {
                    currentMetadata?.serie = serie
                }
            }
            if attributeDict["name"] == "calibre:series_index" {
                if let serieIndex = attributeDict["content"] {
                    currentMetadata?.serieIndex = Int(serieIndex) ?? 0
                }
            }
        }
        if elementName == "dc:identifier" {
            if let uuuid = attributeDict["opf:scheme"]{
                if uuuid == "uuid" {
                    isUUID = true
                } else  {isUUID = false}

            }
        }
    }

    func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
        switch elementName {
        case "dc:identifier":
            if isUUID == true {
                currentMetadata?.uuid = xmlText.trimmingCharacters(in: .whitespacesAndNewlines)
            }
        case "dc:title":
            currentMetadata?.title = xmlText.trimmingCharacters(in: .whitespacesAndNewlines)
        case "dc:creator":
            currentMetadata?.creators.append(xmlText.trimmingCharacters(in: .whitespacesAndNewlines))
        case "metadata":
            if let meta = currentMetadata {
                metadata.append(meta)
            }
        default:
            break

    }
    }

    func parser(_ parser: XMLParser, foundCharacters string: String) {
        xmlText += string
    }
}

class TestMetadata {
func metadataDisplay() {

    if let xmlUrl = Bundle.main.url(forResource: "metadata1", withExtension: "opf") {
        let xml = try! String(contentsOf: xmlUrl)
        let opfParser = OPFParser(withXML: xml)
        let bandeDessinees = opfParser.parse()
        for bandeDessinee in bandeDessinees {
            bandeDessinee.creators = bandeDessinee.creators.filter({ $0 != ""})
            print(bandeDessinee)
        }
    } else {print("fichier non trouvé")}

}
}

let testMetadata = TestMetadata()

testMetadata.metadataDisplay()

Функция metadataDisplay работает и печатает отформатированные метаданные. К сожалению, при переключении на мой проект metadataDisplay ничего не печатает. Массив bandedessinees пуст. Я использую тот же код, за исключением того, что вызываю metadataDisplay с помощью кнопки в файле swiftUI. Я несколько раз пытался реорганизовать код, изменяя класс init () function of my OPFParser, но, к сожалению, не могу понять, почему мои метаданные не выводятся на консоль.

Спасибо за вашу помощь, Айман.

Пример файла metadata.opf:

<?xml version='1.0' encoding='utf-8'?>
<package xmlns="http://www.idpf.org/2007/opf" unique-identifier="uuid_id" version="2.0">
    <metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf">
        <dc:identifier opf:scheme="calibre" id="calibre_id">143</dc:identifier>
        <dc:identifier opf:scheme="uuid" id="uuid_id">03badde9-0932-41ab-bd31-2dbba989a7f5</dc:identifier>
        <dc:title>Tome 1</dc:title>
        <dc:creator opf:file-as="Debeurme, Ludovic" opf:role="aut">Ludovic Debeurme</dc:creator>
        <dc:contributor opf:file-as="calibre" opf:role="bkp">calibre (4.15.0) [https://calibre-ebook.com]</dc:contributor>
        <dc:date>2018-05-20T16:16:27+00:00</dc:date>
        <dc:language>en</dc:language>
        <meta content="{&quot;Ludovic Debeurme&quot;: &quot;&quot;}" name="calibre:author_link_map"/>
        <meta content="Epiphania" name="calibre:series"/>
        <meta content="1" name="calibre:series_index"/>
        <meta content="2020-05-16T13:01:05.580464+00:00" name="calibre:timestamp"/>
        <meta content="Tome 1" name="calibre:title_sort"/>
        <meta name="calibre:user_metadata:#shelves" content="{&quot;table&quot;: &quot;custom_column_1&quot;, &quot;is_editable&quot;: true, &quot;is_custom&quot;: true, &quot;rec_index&quot;: 22, &quot;is_category&quot;: true, &quot;is_multiple2&quot;: {&quot;ui_to_list&quot;: &quot;,&quot;, &quot;list_to_ui&quot;: &quot;, &quot;, &quot;cache_to_list&quot;: &quot;|&quot;}, &quot;name&quot;: &quot;Shelves&quot;, &quot;is_multiple&quot;: &quot;|&quot;, &quot;is_csp&quot;: false, &quot;category_sort&quot;: &quot;value&quot;, &quot;#extra#&quot;: null, &quot;kind&quot;: &quot;field&quot;, &quot;#value#&quot;: [], &quot;display&quot;: {&quot;is_names&quot;: false, &quot;description&quot;: &quot;&quot;}, &quot;search_terms&quot;: [&quot;#shelves&quot;], &quot;datatype&quot;: &quot;text&quot;, &quot;colnum&quot;: 1, &quot;label&quot;: &quot;shelves&quot;, &quot;link_column&quot;: &quot;value&quot;, &quot;column&quot;: &quot;value&quot;}"/>
    </metadata>
    <guide>
        <reference href="cover.jpg" title="Cover" type="cover"/>
    </guide>
</package>

1 Ответ

0 голосов
/ 30 мая 2020

Наконец-то я понял, проблема была в кодировке файла XML. Переключившись с XMLParser(data: Data) на XMLParser(contentsOf: URL), парсер вернул непустой массив.

...