Skip to content

Commit

Permalink
Merge pull request #7 from hironytic/swift3
Browse files Browse the repository at this point in the history
Swift3
  • Loading branch information
hironytic authored Oct 24, 2016
2 parents 95e2df1 + 3a66640 commit 4b39a04
Show file tree
Hide file tree
Showing 12 changed files with 151 additions and 136 deletions.
1 change: 1 addition & 0 deletions .swift-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.0
8 changes: 4 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
# * https://github.com/supermarin/xcpretty#usage

language: objective-c
osx_image: xcode7.3
osx_image: xcode8
# cache: cocoapods
# podfile: Example/Podfile
# before_install:
# - gem install cocoapods # Since Travis is not always on latest version
before_install:
- gem install cocoapods # Since Travis is not always on latest version
# - pod install --project-directory=Example
script:
- set -o pipefail && xcodebuild test -project XMLPullitic/XMLPullitic.xcodeproj -scheme XMLPullitic_iOS -destination 'platform=iOS Simulator,name=iPhone 5s' ONLY_ACTIVE_ARCH=NO | xcpretty
- set -o pipefail && xcodebuild test -project XMLPullitic/XMLPullitic.xcodeproj -scheme XMLPullitic_iOS -destination 'platform=iOS Simulator,name=iPhone 7' ONLY_ACTIVE_ARCH=NO | xcpretty
- pod lib lint --allow-warnings
19 changes: 10 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ if let parser = XMLPullParser(string: xml) {
do {
parsing: while true {
switch try parser.next() {
case .StartDocument:
case .startDocument:
print("start document")
case .StartElement(let name, _, _):
case .startElement(let name, _, _):
print("start element: \(name)")
case .Characters(let text):
case .characters(let text):
print("text: \(text)")
case .EndElement(let name, _):
case .endElement(let name, _):
print("end element: \(name)")
case .EndDocument:
case .endDocument:
print("end document")
break parsing
}
Expand All @@ -39,19 +39,19 @@ Thanks to swift's pattern matching feature, you can easily handle start of eleme
```swift
let event = try parser.next()
switch event {
case .StartElement("foo", _, _):
case .startElement("foo", _, _):
// handle start of <foo>
print("foo: \(event)")
case .StartElement("bar", _, _):
case .startElement("bar", _, _):
// handle start of <bar>
print("bar: \(event)")
case .StartElement("baz", "http://example.com/ns/1.0"?, let element):
case .startElement("baz", "http://example.com/ns/1.0"?, let element):
// handle start of <baz>, whose namespace URI is http://example.com/ns/1.0
// note: you must set parser.shouldProcessNamespaces true to handle namespaces

// you can get attributes from XmlElement object
print(element.attributes["xyz"])
case .StartElement(_, _, _):
case .startElement(_, _, _):
// handle start of other elements
print("other: \(event)")
default:
Expand All @@ -62,6 +62,7 @@ default:
## Requirements

- iOS 8.0+
- Swift 3.0+

## Installation

Expand Down
2 changes: 1 addition & 1 deletion Sources/XMLElement.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// XMLTag.swift
// XMLElement.swift
// XMLPullitic
//
// Copyright (c) 2016 Hironori Ichimiya <[email protected]>
Expand Down
10 changes: 5 additions & 5 deletions Sources/XMLEvent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ import Foundation

public enum XMLEvent {

case StartDocument
case startDocument

case StartElement(name: String, namespaceURI: String?, element: XMLElement)
case startElement(name: String, namespaceURI: String?, element: XMLElement)

case Characters(String)
case characters(String)

case EndElement(name: String, namespaceURI: String?)
case endElement(name: String, namespaceURI: String?)

case EndDocument
case endDocument
}
120 changes: 60 additions & 60 deletions Sources/XMLPullParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,25 +28,25 @@ import Foundation
public class XMLPullParser {
private var internalParser: InternalXMLParser

public convenience init?(contentsOfURL url: NSURL) {
guard let parser = NSXMLParser(contentsOfURL:url) else { return nil }
public convenience init?(contentsOfURL url: URL) {
guard let parser = XMLParser(contentsOf:url) else { return nil }
self.init(xmlParser: parser)
}

public convenience init(data: NSData) {
self.init(xmlParser: NSXMLParser(data: data))
public convenience init(data: Data) {
self.init(xmlParser: XMLParser(data: data))
}

public convenience init(stream: NSInputStream) {
self.init(xmlParser: NSXMLParser(stream: stream))
public convenience init(stream: InputStream) {
self.init(xmlParser: XMLParser(stream: stream))
}

public convenience init?(string: String) {
guard let data = (string as NSString).dataUsingEncoding(NSUTF8StringEncoding) else { return nil }
guard let data = (string as NSString).data(using: String.Encoding.utf8.rawValue) else { return nil }
self.init(data: data)
}

init(xmlParser: NSXMLParser) {
init(xmlParser: XMLParser) {
self.internalParser = InternalXMLParser(xmlParser: xmlParser)
}

Expand Down Expand Up @@ -92,25 +92,25 @@ public class XMLPullParser {

// MARK: -

@objc private class InternalXMLParser: NSObject, NSXMLParserDelegate {
@objc private class InternalXMLParser: NSObject, XMLParserDelegate {
class LockCondition {
static let Requested: Int = 0
static let Provided: Int = 1
}

enum State {
case NotStarted
case Parsing
case Aborted
case Ended
case notStarted
case parsing
case aborted
case ended
}

enum EventOrError {
case Event(XMLEvent)
case Error(ErrorType)
case event(XMLEvent)
case error(Error)
}

let xmlParser: NSXMLParser
let xmlParser: XMLParser
let lock: NSConditionLock
var currentEventOrError: EventOrError
var state: State
Expand All @@ -119,85 +119,85 @@ public class XMLPullParser {

// MARK: methods called on original thread

init(xmlParser: NSXMLParser) {
init(xmlParser: XMLParser) {
self.xmlParser = xmlParser
self.lock = NSConditionLock(condition: LockCondition.Requested)
self.currentEventOrError = EventOrError.Event(XMLEvent.StartDocument)
self.state = .NotStarted
self.currentEventOrError = EventOrError.event(XMLEvent.startDocument)
self.state = .notStarted
self.depth = 0

super.init()
}

func abortParsing() {
guard state == .Parsing else { return }
guard state == .parsing else { return }

state = .Aborted
state = .aborted

// awake wating parser
lock.unlockWithCondition(LockCondition.Requested)
lock.unlock(withCondition: LockCondition.Requested)
}

func requestEvent() throws -> XMLEvent {
switch state {
case .NotStarted:
state = .Parsing
case .notStarted:
state = .parsing
xmlParser.delegate = self
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
self.lock.lockWhenCondition(LockCondition.Requested)
DispatchQueue.global(qos: .default).async {
self.lock.lock(whenCondition: LockCondition.Requested)
self.xmlParser.parse()
}
case .Parsing:
lock.unlockWithCondition(LockCondition.Requested)
case .parsing:
lock.unlock(withCondition: LockCondition.Requested)

case .Aborted:
return XMLEvent.EndDocument
case .aborted:
return XMLEvent.endDocument

case .Ended:
return XMLEvent.EndDocument
case .ended:
return XMLEvent.endDocument
}

lock.lockWhenCondition(LockCondition.Provided)
lock.lock(whenCondition: LockCondition.Provided)
switch currentEventOrError {
case .Error(let error):
state = .Ended
case .error(let error):
state = .ended
lock.unlock()
throw error
case .Event(XMLEvent.EndDocument):
state = .Ended
case .event(XMLEvent.endDocument):
state = .ended
lock.unlock()
return XMLEvent.EndDocument
case .Event(let event):
return XMLEvent.endDocument
case .event(let event):
return event
}
}

// MARK: methods called on background thread

func provide(eventOrError: EventOrError) {
func provide(_ eventOrError: EventOrError) {
if let chars = accumulatedChars {
accumulatedChars = nil
provide(.Event(.Characters(chars)))
provide(.event(.characters(chars)))
waitForNextRequest()
}

if (state == .Parsing) {
if (state == .parsing) {
currentEventOrError = eventOrError
lock.unlockWithCondition(LockCondition.Provided)
lock.unlock(withCondition: LockCondition.Provided)
}
}

func waitForNextRequest() {
guard state == .Parsing else {
if (state == .Aborted && xmlParser.delegate != nil) {
guard state == .parsing else {
if (state == .aborted && xmlParser.delegate != nil) {
xmlParser.delegate = nil
xmlParser.abortParsing()
}
return
}

lock.lockWhenCondition(LockCondition.Requested)
if (state == .Aborted) {
lock.lock(whenCondition: LockCondition.Requested)
if (state == .aborted) {
xmlParser.delegate = nil
xmlParser.abortParsing()
lock.unlock()
Expand All @@ -208,38 +208,38 @@ public class XMLPullParser {
accumulatedChars = (accumulatedChars ?? "") + chars
}

@objc func parserDidStartDocument(parser: NSXMLParser) {
provide(.Event(.StartDocument))
@objc func parserDidStartDocument(_ parser: XMLParser) {
provide(.event(.startDocument))
waitForNextRequest()
}

@objc func parser(parser: NSXMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {
@objc func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {
depth += 1
let element = XMLElement(name: elementName, namespaceURI: namespaceURI, qualifiedName: qName, attributes: attributeDict)
provide(.Event(.StartElement(name: elementName, namespaceURI: namespaceURI, element: element)))
provide(.event(.startElement(name: elementName, namespaceURI: namespaceURI, element: element)))
waitForNextRequest()
}

@objc func parser(parser: NSXMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
provide(.Event(.EndElement(name: elementName, namespaceURI: namespaceURI)))
@objc func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
provide(.event(.endElement(name: elementName, namespaceURI: namespaceURI)))
waitForNextRequest()
depth -= 1
}

@objc func parser(parser: NSXMLParser, foundCharacters string: String) {
@objc func parser(_ parser: XMLParser, foundCharacters string: String) {
accumulate(characters: string)
}

@objc func parserDidEndDocument(parser: NSXMLParser) {
provide(.Event(.EndDocument))
@objc func parserDidEndDocument(_ parser: XMLParser) {
provide(.event(.endDocument))
}

@objc func parser(parser: NSXMLParser, parseErrorOccurred parseError: NSError) {
provide(.Error(XMLPullParserError.ParseError(innerError: parseError)))
@objc func parser(_ parser: XMLParser, parseErrorOccurred parseError: Error) {
provide(.error(XMLPullParserError.parseError(innerError: parseError)))
}

@objc func parser(parser: NSXMLParser, foundCDATA CDATABlock: NSData) {
if let text = NSString(data: CDATABlock, encoding: NSUTF8StringEncoding) {
@objc func parser(_ parser: XMLParser, foundCDATA CDATABlock: Data) {
if let text = NSString(data: CDATABlock, encoding: String.Encoding.utf8.rawValue) {
accumulate(characters: text as String)
}
}
Expand Down
4 changes: 2 additions & 2 deletions Sources/XMLPullParserError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@

import Foundation

public enum XMLPullParserError: ErrorType {
case ParseError(innerError: NSError)
public enum XMLPullParserError: Error {
case parseError(innerError: Error)
}
2 changes: 1 addition & 1 deletion XMLPullitic.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

Pod::Spec.new do |s|
s.name = "XMLPullitic"
s.version = "0.2.2"
s.version = "0.3.0"
s.summary = "Swifty XML pull parser"

s.description = <<-DESC
Expand Down
Loading

0 comments on commit 4b39a04

Please sign in to comment.