TEAM LICENSES: Save money and learn new skills through a Hacking with Swift+ team license >>

how to take the value of child elements XML?

Forums > Swift

Good afternoon everyone. Tell me how to reach the child elements of the XML? Add child elements of <offer> to the structure Offer.

File XML

<yml_catalog date="2023-12-28 17:13">
<shop>
<name>applen1.ru</name>
<company>applen1.ru</company>
<url>https://applen1.ru</url>
<platform>1C-Bitrix</platform>
<currencies>
<currency id="RUB" rate="1"/>
</currencies>
<categories>
<category id="32">Ремонт техники Apple</category>
<category id="15" parentId="32">Ремонт iPhone</category>
<category id="166" parentId="15">Сложный ремонт</category>
<category id="20" parentId="15">Ремонт iPhone 3G/3Gs</category>
</categories>
<offers>
<offer id="188" available="true">
<url>https://applen1.ru/remont/detail/zamena-stekla-iphone-6s/</url>
<price>2590</price>
<currencyId>RUB</currencyId>
<categoryId>94</categoryId>
<categoryId>149</categoryId>
<picture>https://applen1.ru/upload/iblock/5b6/5b6fa009db959cd4d73b0f80dcb2649b.png</picture>
<name>Замена стекла iPhone 6s</name>
<description>Треснуло или разбилось сенсорное стекло iPhone 6S. Экран плохо реагирует на нажатие или самопроизвольно "дергается" при работе.</description>
</offer>
<offer id="198" available="true">
<url>https://applen1.ru/remont/detail/zamena-akkumulyatora-akb-iphone-6s/</url>
<price>1990</price>
<currencyId>RUB</currencyId>
<categoryId>94</categoryId>
<picture>https://applen1.ru/upload/iblock/d18/d18702e7a02df389891e2ea0f5b837d1.jpg</picture>
<name>Замена аккумулятора iPhone 6s</name>
<description>iPhone 6S не включается, быстро садится, плохо заряжается, выключается, не разрядившись полностью.</description>
</offer>
</offers>
</shop>
</yml_catalog>

My code

View

import UIKit
import PlaygroundSupport

final class MyViewController : UIViewController {

    private let customUI = CustomElement()
    private let fileManagert = FileManagerMock()

    private lazy var buttonLoad: UIButton = customUI.createButton()

    private var ooffer: [Offer] = []

    override func loadView() {
        let view = UIView()
        view.backgroundColor = .white

        buttonLoad.frame = CGRect(x: 100, y: 250, width: 200, height: 46)
        buttonLoad.addTarget(self, action: #selector(buttonDidLoad), for: .touchUpInside)

        view.addSubview(buttonLoad)
        self.view = view
    }
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()

Action UI

private extension MyViewController {
    @objc func buttonDidLoad() {
        fileManagert.filePatch { responce in
            switch responce {
                case .success(let data):
                    guard let currentData = data.data(using: .utf8) else { return }
                    let parser = MemoParser(data: currentData)
                    if parser.parse() {

                    }
                case .failure(let error):
                    print("ERROR \(error.localizedDescription)")
            }
        }
    }
}
final class FileManagerMock {
    func filePatch(responceResult: (Result<String, Error>) -> Void) {
        if let filepath = Bundle.main.path(forResource: "ExampleTest", ofType: "xml") {
            do {
                let contents = try String(contentsOfFile: filepath)
                responceResult(.success(contents))
            } catch let error {
                responceResult(.failure(error))
            }
        } else {
            print("Error load file!")
        }
    }
}
struct Offer {
    var offer: String
    var available: String
    var price: String
    var categoryID: [String]
    var description: String
    var name: String
    var id: String
}
final class MemoParser: XMLParser {

    private var category = [String: Any]()
    private var currentElement = ""

    private var offer = Offer(offer: "",
                      available: "String",
                      price: "",
                      categoryID: [],
                      description: "",
                      name: "",
                      id: ""
    )

    private var offers: [Offer] = []

    override init(data: Data) {
        super.init(data: data)
        self.delegate = self
    }
}

extension MemoParser: XMLParserDelegate {

    // Looking for an element 'offer'
    func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {
        switch elementName {
            case "offer":
                // Adding attributes 'id' and 'offer'
                offer = disassembleOffer(dictionary: attributeDict)
            default:
                currentElement = elementName
        }
    }

    // Searching the dictionary by keys
    private func disassembleOffer(dictionary: [String : String]) -> Offer {
        // Temp structure 'Offer'
        var tempOffer = Offer(
            offer: "",
            available: "String",
            price: "",
            categoryID: [],
            description: "",
            name: "",
            id: ""
        )
        for (attr_key, attr_val) in dictionary {
            switch attr_key {
                case "id":
                    tempOffer.id = attr_val
                case "available":
                    tempOffer.available = attr_val
                default:
                    break
            }
        }
        return tempOffer
    }

    func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
        if elementName == "offer" {
            // Add current category in array categoryes
            offers.append(offer)
        }
    }

    // Called when a character sequence is found
    func parser(_ parser: XMLParser, foundCharacters string: String) {
        if !string.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
            if category[currentElement] == nil {
                category.updateValue(string, forKey: currentElement)
            }
        }
    }

    // Called when a CDATA block is found
    func parser(_ parser: XMLParser, foundCDATA CDATABlock: Data) {
        guard String(data: CDATABlock, encoding: .utf8) != nil else {
            print("CDATA contains non-textual data, ignored")
            return
        }
    }
    // Processing completed
    func parserDidEndDocument(_ parser: XMLParser) {
        for (_, offer) in offers.enumerated() {
            print(offer)
        }
    }
}
final class CustomElement {
    func createButton() -> UIButton {
        let button = UIButton()
        button.configuration = .filled()
        button.configuration?.title = "Load"
        button.configuration?.cornerStyle = .medium
        button.configuration?.baseBackgroundColor = .gray

        return button
    }
}

2      

Hacking with Swift is sponsored by Blaze.

SPONSORED Still waiting on your CI build? Speed it up ~3x with Blaze - change one line, pay less, keep your existing GitHub workflows. First 25 HWS readers to use code HACKING at checkout get 50% off the first year. Try it now for free!

Reserve your spot now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.