Skip to content

Commit cfe0448

Browse files
authored
Merge pull request #21 from yahoojapan/swift4.2
Swift4.2 Support
2 parents 1ddcad0 + fcc6a96 commit cfe0448

File tree

16 files changed

+522
-42
lines changed

16 files changed

+522
-42
lines changed

README.md

+85-40
Original file line numberDiff line numberDiff line change
@@ -56,54 +56,95 @@ pod "SwiftyXMLParser", :git => 'https://github.com/yahoojapan/SwiftyXMLParser.gi
5656
# Example
5757

5858
```swift
59-
let string = "<ResultSet><Result><Hit index=\"1\"><Name>Item1</Name></Hit><Hit index=\"2\"><Name>Item2</Name></Hit></Result></ResultSet>"
60-
61-
// parse xml document
62-
xml = try! XML.parse(string)
63-
64-
// access xml element
65-
let accessor = xml["ResultSet"]
66-
67-
// access XML Text
68-
let text = xml["ResultSet", "Result", "Hit", 0, "Name"].text {
69-
print("exsists path & text in XML Element")
70-
}
71-
72-
// access XML Attribute
73-
let index = xml["ResultSet", "Result", "Hit"].attributes?["index"] {
74-
print("exsists path & an attribute in XML Element")
75-
}
76-
77-
// enumerate child Elements in the parent Element
78-
for hit in xml["ResultSet", "Result", "Hit"] {
79-
print("enumarate existing XML Elements")
80-
}
81-
82-
// check if the XML path is wrong
83-
if case .Failure(let error) = xml["ResultSet", "Result", "TypoKey"] {
84-
print(error)
85-
}
59+
import SwiftyXMLParser
60+
61+
let str = """
62+
<ResultSet>
63+
<Result>
64+
<Hit index=\"1\">
65+
<Name>Item1</Name>
66+
</Hit>
67+
<Hit index=\"2\">
68+
<Name>Item2</Name>
69+
</Hit>
70+
</Result>
71+
</ResultSet>
72+
"""
73+
74+
// parse xml document
75+
let xml = try! XML.parse(str)
76+
77+
// access xml element
78+
let accessor = xml["ResultSet"]
79+
80+
// access XML Text
81+
82+
if let text = xml["ResultSet", "Result", "Hit", 0, "Name"].text {
83+
print(text)
84+
}
85+
86+
if let text = xml.ResultSet.Result.Hit[0].Name.text {
87+
print(text)
88+
}
89+
90+
// access XML Attribute
91+
if let index = xml["ResultSet", "Result", "Hit"].attributes["index"] {
92+
print(index)
93+
}
94+
95+
// enumerate child Elements in the parent Element
96+
for hit in xml["ResultSet", "Result", "Hit"] {
97+
print(hit)
98+
}
99+
100+
// check if the XML path is wrong
101+
if case .failure(let error) = xml["ResultSet", "Result", "TypoKey"] {
102+
print(error)
103+
}
86104
```
87105

88106
# Usage
89107
### 1. Parse XML
90108
+ from String
91109
```swift
92-
let string = "<ResultSet><Result><Hit index=\"1\"><Name>Item1</Name></Hit><Hit index=\"2\"><Name>Item2</Name></Hit></Result></ResultSet>"
110+
let str = """
111+
<ResultSet>
112+
<Result>
113+
<Hit index=\"1\">
114+
<Name>Item1</Name>
115+
</Hit>
116+
<Hit index=\"2\">
117+
<Name>Item2</Name>
118+
</Hit>
119+
</Result>
120+
</ResultSet>
121+
"""
93122

94123
xml = try! XML.parse(string) // -> XML.Accessor
95124
```
96125
+ from NSData
97126
```swift
98-
let string = "<ResultSet><Result><Hit index=\"1\"><Name>Item1</Name></Hit><Hit index=\"2\"><Name>Item2</Name></Hit></Result></ResultSet>"
127+
let str = """
128+
<ResultSet>
129+
<Result>
130+
<Hit index=\"1\">
131+
<Name>Item1</Name>
132+
</Hit>
133+
<Hit index=\"2\">
134+
<Name>Item2</Name>
135+
</Hit>
136+
</Result>
137+
</ResultSet>
138+
"""
139+
99140
let data = string.dataUsingEncoding(NSUTF8StringEncoding)
100141

101142
xml = XML.parse(data) // -> XML.Accessor
102143
```
103144

104145
### 2. Access child Elements
105146
```swift
106-
let element = xml["ResultSet"] // -> XML.Accessor
147+
let element = xml.ResultSet // -> XML.Accessor
107148
```
108149

109150
### 3. Access grandchild Elements
@@ -120,20 +161,24 @@ let element = xml[path] // -> <Result><Hit index=\"1\"><Name>Item1</Name></Hit><
120161
```swift
121162
let element = xml["ResultSet", "Result"] // -> <Result><Hit index=\"1\"><Name>Item1</Name></Hit><Hit index=\"2\"><Name>Item2</Name></Hit></Result>
122163
```
164+
+ with @dynamicMemberLookup
165+
```swift
166+
let element = xml.ResultSet.Result // -> <Result><Hit index=\"1\"><Name>Item1</Name></Hit><Hit index=\"2\"><Name>Item2</Name></Hit></Result>
167+
```
123168
### 4. Access specific grandchild Element
124169
```swift
125-
let element = xml["ResultSet", "Result", "Hit", 1] // -> <Hit index=\"2\"><Name>Item2</Name></Hit>
170+
let element = xml.ResultSet.Result.Hit[1] // -> <Hit index=\"2\"><Name>Item2</Name></Hit>
126171
```
127172
### 5. Access attribute in Element
128173
```swift
129-
if let attributeValue = xml["ResultSet", "Result", "Hit", 1].attributes?["index"] {
174+
if let attributeValue = xml.ResultSet.Result.Hit[1].attributes?["index"] {
130175
print(attributeValue) // -> 2
131176
}
132177
```
133178
### 6. Access text in Element
134179
+ with optional binding
135180
```swift
136-
if let text = xml["ResultSet", "Result", "Hit", 1, "Name"].text {
181+
if let text = xml.ResultSet.Result.Hit[1].Name.text {
137182
print(text) // -> Item2
138183
}
139184
```
@@ -143,15 +188,15 @@ struct Entity {
143188
var name = ""
144189
}
145190
let entity = Entity()
146-
entity.name ?= xml["ResultSet", "Result", "Hit", 1, "Name"].text // assign if it has text
191+
entity.name ?= xml.ResultSet.Result.Hit[1].Name.text // assign if it has text
147192
```
148193
+ convert Int and assign
149194
```swift
150195
struct Entity {
151196
var name: Int = 0
152197
}
153198
let entity = Entity()
154-
entity.name ?= xml["ResultSet", "Result", "Hit", 1, "Name"].int // assign if it has Int
199+
entity.name ?= xml.ResultSet.Result.Hit[1].Name.int // assign if it has Int
155200
```
156201
and there are other syntax sugers, bool, url and double.
157202
+ assign text into Array
@@ -160,23 +205,23 @@ struct Entity {
160205
var names = [String]()
161206
}
162207
let entity = Entity()
163-
entity.names ?<< xml["ResultSet", "Result", "Hit", 1, "Name"].text // assign if it has text
208+
entity.names ?<< xml.ResultSet.Result.Hit[1].Name.text // assign if it has text
164209
```
165210
### Check error
166211
```swift
167-
print(xml["ResultSet", "Result", "TypoKey"]) // -> "TypoKey not found."
212+
print(xml.ResultSet.Result.TypoKey) // -> "TypoKey not found."
168213
```
169214

170215
### Access as SequenceType
171216
+ for-in
172217
```swift
173-
for element in xml["ResultSet", "Result", "Hit"] {
218+
for element in xml.ResultSet.Result.Hit {
174219
print(element.text)
175220
}
176221
```
177222
+ map
178223
```swift
179-
xml["ResultSet", "Result", "Hit"].map { $0["Name"].text }
224+
xml.ResultSet.Result.Hit.map { $0.Name.text }
180225
```
181226

182227
## Work with Alamofire
@@ -190,7 +235,7 @@ Alamofire.request(.GET, "https://itunes.apple.com/us/rss/topgrossingapplications
190235
.responseData { response in
191236
if let data = response.data {
192237
let xml = XML.parse(data)
193-
print(xml["feed", "entry", 0, "title"].text) // outputs the top title of iTunes app raning.
238+
print(xml.feed.entry[0].title.text) // outputs the top title of iTunes app raning.
194239
}
195240
}
196241
```

SwiftyXMLParser.xcodeproj/project.pbxproj

+2-2
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@
396396
SKIP_INSTALL = YES;
397397
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
398398
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
399-
SWIFT_VERSION = 4.0;
399+
SWIFT_VERSION = 4.2;
400400
};
401401
name = Debug;
402402
};
@@ -416,7 +416,7 @@
416416
PRODUCT_NAME = "$(TARGET_NAME)";
417417
SKIP_INSTALL = YES;
418418
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
419-
SWIFT_VERSION = 4.0;
419+
SWIFT_VERSION = 4.2;
420420
};
421421
name = Release;
422422
};

SwiftyXMLParser/Accessor.swift

+6
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ extension XML {
3939

4040

4141
*/
42+
@dynamicMemberLookup
4243
public enum Accessor: CustomStringConvertible, Swift.Sequence {
4344
case singleElement(Element)
4445
case sequence([Element])
@@ -56,6 +57,11 @@ extension XML {
5657
self = .failure(error)
5758
}
5859

60+
61+
public subscript(dynamicMember member: String) -> XML.Accessor {
62+
return self[member]
63+
}
64+
5965
/**
6066
If Accessor object has a correct XML path, return XML element, otherwith return error
6167

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import SwiftyXMLParser
2+
3+
let str = """
4+
<ResultSet>
5+
<Result>
6+
<Hit index=\"1\">
7+
<Name>Item1</Name>
8+
</Hit>
9+
<Hit index=\"2\">
10+
<Name>Item2</Name>
11+
</Hit>
12+
</Result>
13+
</ResultSet>
14+
"""
15+
16+
// parse xml document
17+
let xml = try! XML.parse(str)
18+
19+
// access xml element
20+
let accessor = xml["ResultSet"]
21+
22+
// access XML Text
23+
24+
if let text = xml["ResultSet", "Result", "Hit", 0, "Name"].text {
25+
print(text)
26+
}
27+
28+
if let text = xml.ResultSet.Result.Hit[0].Name.text {
29+
print(text)
30+
}
31+
32+
// access XML Attribute
33+
if let index = xml["ResultSet", "Result", "Hit"].attributes["index"] {
34+
print(index)
35+
}
36+
37+
// enumerate child Elements in the parent Element
38+
for hit in xml["ResultSet", "Result", "Hit"] {
39+
print(hit)
40+
}
41+
42+
// check if the XML path is wrong
43+
if case .failure(let error) = xml["ResultSet", "Result", "TypoKey"] {
44+
print(error)
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2+
<playground version='5.0' target-platform='ios' executeOnSourceChanges='false'>
3+
<timeline fileName='timeline.xctimeline'/>
4+
</playground>
+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//
2+
// AppDelegate.swift
3+
// iOS Sample
4+
//
5+
// Created by Kazuhiro Hayashi on 2018/07/02.
6+
// Copyright © 2018年 Kazuhiro Hayashi. All rights reserved.
7+
//
8+
9+
import UIKit
10+
11+
@UIApplicationMain
12+
class AppDelegate: UIResponder, UIApplicationDelegate {
13+
14+
var window: UIWindow?
15+
16+
17+
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
18+
// Override point for customization after application launch.
19+
return true
20+
}
21+
22+
func applicationWillResignActive(_ application: UIApplication) {
23+
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
24+
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
25+
}
26+
27+
func applicationDidEnterBackground(_ application: UIApplication) {
28+
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
29+
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
30+
}
31+
32+
func applicationWillEnterForeground(_ application: UIApplication) {
33+
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
34+
}
35+
36+
func applicationDidBecomeActive(_ application: UIApplication) {
37+
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
38+
}
39+
40+
func applicationWillTerminate(_ application: UIApplication) {
41+
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
42+
}
43+
44+
45+
}
46+

0 commit comments

Comments
 (0)