• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • SwiftUI學習筆記【XML解析】

    標簽: IOS專欄  IOS XML解析  Swift xml解析  SwiftUI xml解析  xml

    前言

    xml解析百度很多都是OC,我們來干一波Swift吧,群里大佬比較多,語法不會的問大佬,編譯器不會的問大佬,炒股的問大佬…Q裙:730772561 大佬太多,不慌。


    今日提示:知恥下問,后發先至。

    一、XMLParser的了解

    對于接觸過IOS解析XML的應該很多吧…我是寫Android的我司項目會涉及到很多xml解析導出給CAD然后CAD解析完成之后進行繪制編輯等。原生Android有很多對于XML的解析方式[SAX,Pull,DOM等],Flutter的對于XML解析很少了之前就見過XML這個庫。

    • 在使用最原始的XMLParser之前,我百度看過其他人封裝的解析器,在分離方面顯的很麻煩。對于類的構建要求比較高,如果涉及到上千節點的的xml那就太過于麻煩。我們先來最原始基本的,說不定是最舒服的方式。在Swift里面XMLParser為我們開發提供了便利,如下我們看看源碼也就三個初始化構造函數init(..),一個開始解析的方法parse(),一個解析器委托delegate,其實最主要的就是解析器委托了,所有解析的過程都交付委托給解析器委托delegate工具了。
    open class XMLParser : NSObject {
    
        //url初始化也可以
        public convenience init?(contentsOf url: URL)
        //根據文件字節bytes data初始化也可以
        public init(data: Data)
        //stream初始化也可以
        @available(iOS 5.0, *) 
        public convenience init(stream: InputStream)
    
        //XML解析器委托
        unowned(unsafe) open var delegate: XMLParserDelegate?
        
        open var shouldProcessNamespaces: Bool
    
        open var shouldReportNamespacePrefixes: Bool
        
        @available(iOS 8.0, *)
        open var externalEntityResolvingPolicy: XMLParser.ExternalEntityResolvingPolicy
        
        @available(iOS 8.0, *)
        open var allowedExternalEntityURLs: Set<URL>?
    
        open func parse() -> Bool
    
        open func abortParsing()
     
        open var parserError: Error? { get }
     
        open var shouldResolveExternalEntities: Bool
    }
    
    

    二、新建xml文件且導入項目

    1.新建.xml文件然后寫入你想解析的節點或者已有的及其復雜的.xml文件。我的如下(粘貼的):

    <?xml version="1.0" encoding="utf-8"?>
    <Users>
        <User id="101">
            <name>航歌</name>
            <tel>
                <mobile>1234567</mobile>
                <home>025-8100000</home>
            </tel>
        </User>
        <User id="102">
            <name>hangge</name>
            <tel>
                <mobile>8989889</mobile>
                <home>025-8122222</home>
            </tel>
        </User>
    </Users>
    
    

    2.導入xml

    如圖操作即可和上一篇SwiftUI學習筆記[Sqlite]一樣一樣的。

    三.解析xml

    1.新建結構

    我們根據xml的內容來新建數據模型對于數據模型是你的需求所決定的。這里也就演變出不同的解析過程對于賦值方式的不同。有些人的數據模型如下說我只想要個User其他的內部節點作為其內部屬性:

    //struct也行
    struct MyUser{
        var id: String?  //編號
        var name: String? //姓名
        var tel:Tel?//電話
        class Tel {
            var mobile: String? //手機
            var home: String? //固話
        }
    }
    //class 也行都為來儲存數據。
    class MyUser {
        var id: String?  //編號
        var name: String? //姓名
        var tel:Tel?//電話
        class Tel {
            var mobile: String? //手機
            var home: String? //固話
        }
    }
    

    有些人需要分開User和Tel這是一個舉例。但是在實際中我們對于父子節點來說是其類–>屬性,但是可能xml作為接口文件。而當前頁面只需要Tel不需要整體,解析那更簡單了。

        class Tel {
            var mobile: String? //手機
            var home: String? //固話
        }
    

    2.解析器委托進行解析。

    XML解析器委托:XMLParserDelegate作為代理接口協議,定義了解析過程所

    【1】:節點屬性解析

    解析器,必須每個節點的開始和結束都需要提供接口去解析成模型,如下代碼:每次到一個節點開始都會調用下面方法–>這時我們進行創建對應的數據類class或者模型結構struct.

    <?xml version="1.0" encoding="utf-8"?>
    <Users xmlns ="http://www.example.com/DEFAULT">
        <User id="101" uid="2021 come on">
            <name>航歌</name>
            <tel>
                <mobile>1234567</mobile>
                <home>025-8100000</home>
            </tel>
        </User>
        <User id="102">
            <name>hangge</name>
            <tel>
                <mobile>8989889</mobile>
                <home>025-8122222</home>
            </tel>
        </User>
    </Users>
    
    
    elementNamenamespaceURIqualifiedNameattributes
    每個節點起始名稱命名空間限定名稱屬性
    如上面:User,User,tel等
    有自節點,而不是字符節點
    如:<name>航歌</name>
    相當于身份標示命
    名,學過前端的都明白
    XML第一節課估計
    就是
    本地名?百度百度節點屬性是如上id=“101”
    uid=“2021 come on”,
    而不是子節點
    <elementName >
      <otherElementName>
    xmlns =“http://www.exa
    mple.com/DEFAULT”
    attributeDict[“id”],attributeDict[“uid”]
         // 遇到一個開始標簽時調用
        func parser(_ parser: XMLParser, didStartElement elementName: String,
                       namespaceURI: String?, qualifiedName qName: String?,
                       attributes attributeDict: [String : String] = [:]) {
                       }
    
    • 進行創建對應的數據類或者模型結構.
        // 遇到一個開始標簽時調用
        func parser(_ parser: XMLParser, didStartElement elementName: String,
                       namespaceURI: String?, qualifiedName qName: String?,
                       attributes attributeDict: [String : String] = [:]) {
               currentElement = elementName
            //每個節點名的開始就是我們要不要實例化模型或者類。
            switch elementName {
                case "User":
                    //創建一個新用戶對象
                    user = MyUser()
                    //保存下id
                    user.id = attributeDict["id"]
                case "tel":
                    tel = MyUser.Tel()
                default:
                  break
                
           }
        }
    
    
    【2】:解析字符節點
    foundCharacters
    每個字符節點內容
    <name>航歌<name>
       // 遇到字符串時調用
         func parser(_ parser: XMLParser, foundCharacters string: String) {
               //這里只是去去空格過濾字符的。別感覺到太難了
               let data = string.trimmingCharacters(in: .whitespacesAndNewlines)
               //接下來每遇到一個字符,將該字符追加到相應的 property 中
               switch currentElement{
               case "name":
                   user.name = user.name ?? "" + data
               case "mobile":
                   tel.mobile = tel.mobile ?? "" +  data
               case "home":
                   tel.home = tel.home ?? "" + data
               default:
                   break
               }
           }                
    
    
    import UIKit
    import SwiftEventBus
    
    class XMLUtils:NSObject, XMLParserDelegate{
        //保存最終解析的結果
         var users:[MyUser] = []
         static let mself=XMLUtils()
         //當前元素名
         var currentElement = ""
          
         //當前用戶
         var user:MyUser!
         var tel:MyUser.Tel!
        
        
        
        
        // 遇到一個開始標簽時調用
        func parser(_ parser: XMLParser, didStartElement elementName: String,
                       namespaceURI: String?, qualifiedName qName: String?,
                       attributes attributeDict: [String : String] = [:]) {
               currentElement = elementName
    
            switch elementName {
                case "User":
                    //創建一個新用戶對象
                    user = MyUser()
                    //保存下id
                    user.id = attributeDict["id"]
                case "tel":
                    tel = MyUser.Tel()
                default:
                  break
                
           }
        }
        
        
            
         // 遇到字符串時調用
         func parser(_ parser: XMLParser, foundCharacters string: String) {
               let data = string.trimmingCharacters(in: .whitespacesAndNewlines)
               //接下來每遇到一個字符,將該字符追加到相應的 property 中
               switch currentElement{
               case "name":
                   user.name = user.name ?? "" + data
               case "mobile":
                   tel.mobile = tel.mobile ?? "" +  data
               case "home":
                   tel.home = tel.home ?? "" + data
               default:
                   break
               }
           }
        
        
            
        // 遇到結束標簽時調用
        func parser(_ parser: XMLParser, didEndElement elementName: String,
                       namespaceURI: String?, qualifiedName qName: String?) {
               //標簽User結束時將該用戶對象,存入數組容器。
            switch elementName {
            case "User":
                users.append(user)
            case "tel":
                user.tel=tel
            default:
                break
            }
            
            
           
        }
    
        func parserDidEndDocument(_ parser: XMLParser) {
            //輸出結果
            for i in 0...(users.count - 1 ){
                if let tel = users[i].tel  {
                    if let mobile = tel.mobile {
                    print("User: id:\(users[i].id!),name:\(users[i].name!),"
                            + "mobile:\(mobile),"
                            + "home:\(tel.home)")
                    }
                }
                
            }
            SwiftEventBus.post("personFetchEvent", sender:users[0])
        }
        //用戶對象
      
    }
    
    

    四.調用展示

    //
    //  SwiftUI_XML_View.swift
    //  swiftUiStudy
    //
    //  Created by 王飛 on 2020/12/2.
    //
    
    import SwiftUI
    import SwiftEventBus
    struct SwiftUI_XML_View: View{
        //記錄當前節點的名字
        var currentNodeName:String!
        @State var xmlName:String! = "解析結果"
        
        var body: some View {
            
            Text("\(xmlName)").onTapGesture {
                let xmlUrl = URL(fileURLWithPath: Bundle.main.path(forResource: "users", ofType: "xml")!)
                let parser = XMLParser(contentsOf:xmlUrl)
                print("解析開始")
                //設置delegate
                parser?.delegate=XMLUtils.mself
                //開始解析
                parser?.parse()
                
                SwiftEventBus.onMainThread(XMLUtils(), name:"personFetchEvent") { result in
                    let user : MyUser = result!.object! as! MyUser
                    print(user.name) // will output "john doe"
                    xmlName=user.name
                }
               
            }
        }
        
        
     
    }
    
    struct SwiftUI_XML_View_Previews: PreviewProvider{
        static var previews: some View {
            SwiftUI_XML_View()
        }
    }
    
    

    版權聲明:本文為m0_37667770原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
    本文鏈接:https://blog.csdn.net/m0_37667770/article/details/110850023

    智能推薦

    SwiftUI學習筆記之Animations

    SwiftUI學習筆記之Animations 一 SwiftUI的Animations可以用到View當中,不僅是數值變化可以使用,即使是布爾變量也可以使用,例如在Button中使用 當點擊button時,背景顏色立刻變為藍色或者紅色。如果我們加上animation 則顏色變化則漸變為紅色或者藍色。 除了默認的動畫模式還有很多可供選擇 比如 interpolatingSpring easeInOu...

    SwiftUI學習筆記[path繪制]

    前言 繪制的底層是強大的,我們所用的各端語言只是在現代UI追求的步伐中和用戶喜好的交互中求同存異,抽取封裝出自成個性風格的UI控件,當然面對萬億級別的客戶各個平臺的UI庫出也不可能滿足所有的客戶需求,當然一門語言的可制定性也意味著其強大,幾乎每個平臺都提供了接口讓開發者創造其UI的可能性,更可能的能滿足客戶需求。 一,Path 繪制【直線、圓弧、圓錐曲線、貝塞爾曲線等】 1.Path SwiftU...

    XML學習---XML文檔解析

    Java對XML文檔進行解析 解析XML的幾種方式的概述; JAXP(JavaApi for Xml Programming) – sun公司的一套操作XML的API. DOM解析-一次性的將數據全部裝入內存。 SAX解析-邊讀取邊解析 Dom4j(Document For Java)-第三方開源,是從jdom分裂出來的解析技術。目前jdom已經完全被dom4j替代。 jDom &nd...

    java學習筆記:使用dom4j解析xml

    最近寫程序需要用java解析xml文件,于是在網上借鑒了一下“殘缺的孤獨”的博客,使用了dom4j方法。   xml格式如下: 解析的核心代碼: 其中該xml的根節點即為award,AwardTitle、AwardAmount等均為根節點之下的子節點。 先介紹一下e.elementText()、e.element()、e.elements()三種方法的區別:e.e...

    HTML中常用操作關于:頁面跳轉,空格

    1.頁面跳轉 2.空格的代替符...

    猜你喜歡

    freemarker + ItextRender 根據模板生成PDF文件

    1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...

    電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!

    Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...

    requests實現全自動PPT模板

    http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...

    Linux C系統編程-線程互斥鎖(四)

    互斥鎖 互斥鎖也是屬于線程之間處理同步互斥方式,有上鎖/解鎖兩種狀態。 互斥鎖函數接口 1)初始化互斥鎖 pthread_mutex_init() man 3 pthread_mutex_init (找不到的情況下首先 sudo apt-get install glibc-doc sudo apt-get install manpages-posix-dev) 動態初始化 int pthread_...

    精品国产乱码久久久久久蜜桃不卡