[Swift通天遁地]七、数据与安全-(2)对XML和HTML文档的快速解析
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公众号:山青咏芝(shanqingyongzhi)
➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/)
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:https://www.cnblogs.com/strengthen/p/10300747.html
➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
本文将演示使用Fuzi(斧子)类库实现对XML和HTML文档的快速解析。
首先确保在项目中已经安装了所需的第三方库。
点击【Podfile】,查看安装配置文件。
1 platform :ios, '12.0' 2 use_frameworks! 3 4 target 'DemoApp' do 5 source 'https://github.com/CocoaPods/Specs.git' 6 pod 'Fuzi' 7 end
根据配置文件中的相关配置,安装第三方库。
然后点击打开【DemoApp.xcworkspace】项目文件。
在项目导航区,打开视图控制器的代码文件【ViewController.swift】
1 import UIKit 2 //引入已经安装的第三方类库 3 import Fuzi 4 5 class ViewController: UIViewController { 6 7 override func viewDidLoad() { 8 super.viewDidLoad() 9 // Do any additional setup after loading the view, typically from a nib. 10 //实现对XML文档的解析 11 parseXML() 12 //实现对HTML文档的解析 13 parseHTML() 14 } 15 16 //添加一个方法,实现对XML文档的解析 17 func parseXML() 18 { 19 //从项目中读取指定文件名称的待解析的文档。 20 let fileUrl = URL(fileURLWithPath: ((#file as NSString).deletingLastPathComponent as NSString).appendingPathComponent("nutrition.xml")) 21 //添加一个异常捕捉语句,用来处理对XML文档的解析操作。 22 do 23 { 24 //读取待解析的文档,并存储在一个数据常量中。 25 let data = try Data(contentsOf: fileUrl) 26 //将加载的数据转换成文档对象。 27 let document = try XMLDocument(data: data) 28 29 //获得文档对象的根节点,并在控制台输出根节点的标签的值。 30 if let root = document.root 31 { 32 //输出日志信息 33 print("Root Element: \(String(describing: root.tag))") 34 35 print("\nDaily values:") 36 //获得根节点中指定标签的节点, 37 //然后获得该节点下的所有子节点, 38 //并对子节点进行遍历。 39 for element in root.firstChild(tag: "daily-values")?.children ?? [] 40 { 41 //获得节点标签的名称 42 let nutrient = element.tag 43 //获得节点的值 44 let amount = element.numberValue 45 //获得节点属性的值 46 let unit = element["units"] 47 //在控制台输出节点各元素的值 48 print("- \(amount!)\(unit!) \(nutrient!)") 49 } 50 //输出一个换行符 51 print("\n") 52 53 //通过X路径格式,获得指定的节点。 54 //这里获得食物节点下的名称子节点。 55 var xpath = "//food/name" 56 //在控制台输出该节点。 57 print("XPath Search: \(xpath)") 58 59 //遍历所有的名称节点 60 for element in document.xpath(xpath) 61 { 62 //并在控制台输出食物的名称 63 print("\(element)") 64 } 65 //输出另一个换行符 66 print("\n") 67 68 //还可以通过和CSS相似的方法,来查找指定的节点。 69 //这里获得食物节点下的指定的子节点。 70 let css = "food > serving[units]" 71 //初始化一个文档元素 72 var blockElement:XMLElement? = nil 73 //在控制台输出搜索路径 74 print("CSS Search: \(css)") 75 76 //对指定路径下的节点进行遍历 77 for (index, element) in document.css(css).enumerated() 78 { 79 //当循环的索引为数字1时, 80 if index == 1 81 { 82 //获得遍历的节点。 83 blockElement = element 84 break 85 } 86 } 87 //然后在控制台输出第二个节点。 88 print("Second element: \(blockElement!)\n") 89 90 //在控制台输出食物节点下的,名称子节点的X路径。 91 xpath = "//food/name" 92 print("XPath Search: \(xpath)") 93 94 //获得文档中的指定路径的第一个节点, 95 //在控制台输出该节点的内容。 96 let firstElement = document.firstChild(xpath: xpath)! 97 print("First element: \(firstElement)") 98 } 99 } 100 catch 101 { 102 print("Something went wrong :(") 103 } 104 } 105 106 //添加一个方法,实现对HTML文档的解析 107 func parseHTML() 108 { 109 //从项目中读取指定的网页文件 110 let fileUrl = URL(fileURLWithPath: ((#file as NSString).deletingLastPathComponent as NSString).appendingPathComponent("index.html")) 111 //添加一个异常捕捉语句,用来处理对HTML文档的解析操作。 112 do 113 { 114 //获得指定位置的网页文件,将文件存储在数据对象中。 115 let data = try Data(contentsOf: fileUrl) 116 //将网页数据转换成文档对象。 117 let doc = try HTMLDocument(data: data) 118 119 //获得文档对象中的第一个指定的节点, 120 if let elementById = doc.firstChild(css: "#copyright") 121 { 122 //并在控制台输出该节点的内容。 123 print(elementById.stringValue) 124 } 125 126 //获得文档对象中的所有链接节点, 127 //并对链接节点进行遍历 128 for link in doc.css("a, link") 129 { 130 //在控制台输出链接的路径 131 print(link.rawXML) 132 print(link["href"] as Any) 133 } 134 135 //获得主体节点下的所有链接节点, 136 if let firstAnchor = doc.firstChild(xpath: "//body/a") 137 { 138 //并输出第一个网络链接。 139 print(firstAnchor["href"] as Any) 140 } 141 142 //获得头结点下的所有脚本节点, 143 for script in doc.xpath("//head/script") 144 { 145 //并输出脚本节点的文档路径 146 print(script["src"] ?? "") 147 } 148 149 //获得主体节点下的所有链接节点, 150 if let result = doc.eval(xpath: "count(//body/a)") 151 { 152 //并在控制台输出该数量 153 print("anchor count : \(result.doubleValue)") 154 } 155 156 //输出标题 157 print(doc.title as Any) 158 //输出头节点 159 print(doc.head as Any) 160 //输出主题节点 161 print(doc.body as Any) 162 } 163 catch 164 { 165 print("Something went wrong :(") 166 } 167 } 168 169 override func didReceiveMemoryWarning() { 170 super.didReceiveMemoryWarning() 171 // Dispose of any resources that can be recreated. 172 } 173 }