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>
elementName | namespaceURI | qualifiedName | attributes |
---|---|---|---|
每個節點起始名稱 | 命名空間 | 限定名稱 | 屬性 |
如上面: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()
}
}
智能推薦
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...
猜你喜歡
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_...