diff --git a/LICENSE b/LICENSE
new file mode 100755
index 0000000..62b0285
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 Yahoo Japan Corporation
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100755
index 0000000..89f1754
--- /dev/null
+++ b/README.md
@@ -0,0 +1,183 @@
+# SwiftyXMLParser
+[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) ![Cocoapods compatible](https://cocoapod-badges.herokuapp.com/v/SwiftyXMLParser/badge.png)
+
+
+Simple XML Parser implemented by Swift
+
+# What's this?
+This is a XML parser inspired by [SwiftyJSON](https://github.com/SwiftyJSON/SwiftyJSON) and [SWXMLHash](https://github.com/drmohundro/SWXMLHash).
+
+[NSXMLParser](https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSXMLParser_Class/) in Foundation framework is a kind of "SAX" parser. It has a enough performance but is a little inconvenient. So we have implemented "DOM" parser wrapping it.
+
+# Feature
+- [x] access XML Document with "subscript" literal.
+- [x] access XML Document as SequenceType.
+- [x] debug wrong XML pathes easily.
+
+# Requirement
++ iOS 7.0+
++ Swift 2.0+
+
+# Installation
+
+### Carthage
+#### 1. create Cartfile
+
+```ruby:Cartfile
+github "https://github.com/yahoojapan/SwiftyXMLParser"
+
+```
+#### 2. install
+```
+> carthage update
+```
+
+### CocoaPods
+#### 1. create Podfile
+```ruby:Podfile
+platform :ios, '8.0'
+use_frameworks!
+
+pod "SwiftyXMLParser", :git => 'https://github.com/yahoojapan/SwiftyXMLParser.git'
+```
+
+#### 2. install
+```
+> pod install
+```
+
+# Example
+
+```swift
+ let string = "Item1Item2"
+
+ // parse xml document
+ xml = try! XML.parse(string)
+
+ // access xml element
+ let accessor = xml["ResultSet"]
+
+ // access XML Text
+ let text = xml["ResultSet", "Result", "Hit", 0, "Name"].text {
+ print("exsists path & text in XML Element")
+ }
+
+ // access XML Attribute
+ let index = xml["ResultSet", "Result", "Hit"].attributes?["index"] {
+ print("exsists path & an attribute in XML Element")
+ }
+
+ // enumerate child Elements in the parent Element
+ for hit in xml["ResultSet", "Result", "Hit"] {
+ print("enumarate existing XML Elements")
+ }
+
+ // check if the XML path is wrong
+ if case .Failure(let error) = xml["ResultSet", "Result", "TypoKey"] {
+ print(error)
+ }
+```
+
+# Usage
+### 1. Parse XML
++ from String
+```swift
+let string = "Item1Item2"
+
+xml = try! XML.parse(string) // -> XML.Accessor
+```
++ from NSData
+```swift
+let string = "Item1Item2"
+let data = string.dataUsingEncoding(NSUTF8StringEncoding)
+
+xml = try! XML.parse(data) // -> XML.Accessor
+```
+
+### 2. Access child Elements
+```swift
+let element = xml["ResultSet"] // -> XML.Accessor
+```
+
+### 3. Access grandchild Elements
++ with String
+```swift
+let element = xml["ResultSet"]["Result"] // -> Item1Item2
+```
++ with Array
+```swift
+let path = ["ResultSet", "Result"]
+let element = xml[path] // -> Item1Item2
+```
++ with Variadic
+```swift
+let element = xml["ResultSet", "Result"] // -> Item1Item2
+```
+### 4. Access specific grandchild Element
+```swift
+let element = xml["ResultSet", "Result", "Hit", 1] // -> Item2
+```
+### 5. Access attribute in Element
+```swift
+if let attributeValue = xml["ResultSet", "Result", "Hit", 1].attributes?["index"] {
+ print(attributeValue) // -> 2
+}
+```
+### 6. Access text in Element
++ with optional binding
+```swift
+if let text = xml["ResultSet", "Result", "Hit", 1, "Name"].text {
+ print(text) // -> Item2
+}
+```
++ with custom operation
+```swift
+struct Entity {
+ var name = ""
+}
+let entity = Entity()
+entity.name ?= xml["ResultSet", "Result", "Hit", 1, "Name"].text // assign if it has text
+```
++ convert Int and assign
+```swift
+struct Entity {
+ var name: Int = 0
+}
+let entity = Entity()
+entity.name ?= xml["ResultSet", "Result", "Hit", 1, "Name"].int // assign if it has Int
+```
+and there are other syntax sugers, bool, url and double.
++ assign text into Array
+```swift
+struct Entity {
+ var names = [String]()
+}
+let entity = Entity()
+entity.names ?<< xml["ResultSet", "Result", "Hit", 1, "Name"].text // assign if it has text
+```
+### Check error
+```swift
+print(xml["ResultSet", "Result", "TypoKey"]) // -> "TypoKey not found."
+```
+
+### Access as SequenceType
++ for-in
+```swift
+for element in xml["ResultSet", "Result", "Hit"] {
+ print($0.text)
+}
+```
++ map
+```swift
+xml["ResultSet", "Result", "Hit"].map { $0["Name"].text }
+```
++ filter
+```swift
+xml["ResultSet", "Result", "Hit"].filter { $0["Name"].text != "Item2" }
+```
+
+etc...
+
+# License
+
+This software is released under the MIT License, see LICENSE.
diff --git a/SwiftyXMLParser.podspec b/SwiftyXMLParser.podspec
new file mode 100755
index 0000000..845c30b
--- /dev/null
+++ b/SwiftyXMLParser.podspec
@@ -0,0 +1,22 @@
+Pod::Spec.new do |s|
+ s.name = "SwiftyXMLParser"
+ s.version = "1.0.0"
+ s.summary = "Simple XML Parser implemented by Swift"
+
+ s.description = <<-DESC
+ This is a XML parser inspired by SwiftyJSON and SWXMLHash.
+
+ NSXMLParser in Foundation framework is a kind of "SAX" parser. It has a enough performance but is a little inconvenient.
+ So we have implemented "DOM" parser wrapping it.
+ DESC
+
+ s.homepage = "https://github.com/yahoojapan/SwiftyXMLParser.git"
+ s.license = "MIT"
+ s.author = { "kahayash" => "kahayash@yahoo-corp.jp" }
+
+ s.ios.deployment_target = "8.0"
+ s.source_files = "SwiftyXMLParser/*.swift"
+ s.requires_arc = true
+
+ s.source = { :git => "https://github.com/yahoojapan/SwiftyXMLParser.git", :tag => "1.0.0" }
+end
diff --git a/SwiftyXMLParser.xcodeproj/project.pbxproj b/SwiftyXMLParser.xcodeproj/project.pbxproj
new file mode 100755
index 0000000..cd620b3
--- /dev/null
+++ b/SwiftyXMLParser.xcodeproj/project.pbxproj
@@ -0,0 +1,452 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 2B225AAF1CBCBA40002282BD /* SimpleDocument.xml in Resources */ = {isa = PBXBuildFile; fileRef = 2B225AAE1CBCBA40002282BD /* SimpleDocument.xml */; };
+ 2B6D92371C7F0587000D2D06 /* SwiftyXMLParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B6D92361C7F0587000D2D06 /* SwiftyXMLParser.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2B6D923E1C7F0587000D2D06 /* SwiftyXMLParser.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2B6D92331C7F0587000D2D06 /* SwiftyXMLParser.framework */; };
+ 2B6D92431C7F0587000D2D06 /* SwiftyXMLParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B6D92421C7F0587000D2D06 /* SwiftyXMLParserTests.swift */; };
+ 2B6D92511C7F059B000D2D06 /* XML.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B6D924D1C7F059B000D2D06 /* XML.swift */; };
+ 2B6D92521C7F059B000D2D06 /* Element.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B6D924E1C7F059B000D2D06 /* Element.swift */; };
+ 2B6D92531C7F059B000D2D06 /* Accessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B6D924F1C7F059B000D2D06 /* Accessor.swift */; };
+ 2B6D92541C7F059B000D2D06 /* Parser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B6D92501C7F059B000D2D06 /* Parser.swift */; };
+ 2BD9432B1CB220E0007D5FFC /* XMLTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BD9432A1CB220E0007D5FFC /* XMLTests.swift */; };
+ 2BD9432D1CB220E5007D5FFC /* ParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BD9432C1CB220E5007D5FFC /* ParserTests.swift */; };
+ 2BD9432F1CB220EA007D5FFC /* AccessorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BD9432E1CB220EA007D5FFC /* AccessorTests.swift */; };
+ 2BD943311CB220F1007D5FFC /* CustomOperatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BD943301CB220F1007D5FFC /* CustomOperatorTests.swift */; };
+ 2BD943341CB22107007D5FFC /* BrokenXMLDocument.xml in Resources */ = {isa = PBXBuildFile; fileRef = 2BD943331CB22107007D5FFC /* BrokenXMLDocument.xml */; };
+ 2BD943361CB2210D007D5FFC /* XMLDocument.xml in Resources */ = {isa = PBXBuildFile; fileRef = 2BD943351CB2210D007D5FFC /* XMLDocument.xml */; };
+ 2BD943381CB23CFE007D5FFC /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BD943371CB23CFE007D5FFC /* Error.swift */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 2B6D923F1C7F0587000D2D06 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 2B6D922A1C7F0587000D2D06 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 2B6D92321C7F0587000D2D06;
+ remoteInfo = SwiftyXMLParser;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+ 2B225AAE1CBCBA40002282BD /* SimpleDocument.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = SimpleDocument.xml; sourceTree = ""; };
+ 2B6D92331C7F0587000D2D06 /* SwiftyXMLParser.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SwiftyXMLParser.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ 2B6D92361C7F0587000D2D06 /* SwiftyXMLParser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SwiftyXMLParser.h; sourceTree = ""; };
+ 2B6D92381C7F0587000D2D06 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ 2B6D923D1C7F0587000D2D06 /* SwiftyXMLParserTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SwiftyXMLParserTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 2B6D92421C7F0587000D2D06 /* SwiftyXMLParserTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftyXMLParserTests.swift; sourceTree = ""; };
+ 2B6D92441C7F0587000D2D06 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ 2B6D924D1C7F059B000D2D06 /* XML.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XML.swift; sourceTree = ""; };
+ 2B6D924E1C7F059B000D2D06 /* Element.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Element.swift; sourceTree = ""; };
+ 2B6D924F1C7F059B000D2D06 /* Accessor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Accessor.swift; sourceTree = ""; };
+ 2B6D92501C7F059B000D2D06 /* Parser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Parser.swift; sourceTree = ""; };
+ 2BD9432A1CB220E0007D5FFC /* XMLTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XMLTests.swift; sourceTree = ""; };
+ 2BD9432C1CB220E5007D5FFC /* ParserTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ParserTests.swift; sourceTree = ""; };
+ 2BD9432E1CB220EA007D5FFC /* AccessorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccessorTests.swift; sourceTree = ""; };
+ 2BD943301CB220F1007D5FFC /* CustomOperatorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomOperatorTests.swift; sourceTree = ""; };
+ 2BD943331CB22107007D5FFC /* BrokenXMLDocument.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = BrokenXMLDocument.xml; sourceTree = ""; };
+ 2BD943351CB2210D007D5FFC /* XMLDocument.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = XMLDocument.xml; sourceTree = ""; };
+ 2BD943371CB23CFE007D5FFC /* Error.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Error.swift; sourceTree = ""; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 2B6D922F1C7F0587000D2D06 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 2B6D923A1C7F0587000D2D06 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 2B6D923E1C7F0587000D2D06 /* SwiftyXMLParser.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 2B6D92291C7F0587000D2D06 = {
+ isa = PBXGroup;
+ children = (
+ 2B6D92351C7F0587000D2D06 /* SwiftyXMLParser */,
+ 2B6D92411C7F0587000D2D06 /* SwiftyXMLParserTests */,
+ 2B6D92341C7F0587000D2D06 /* Products */,
+ );
+ sourceTree = "";
+ };
+ 2B6D92341C7F0587000D2D06 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 2B6D92331C7F0587000D2D06 /* SwiftyXMLParser.framework */,
+ 2B6D923D1C7F0587000D2D06 /* SwiftyXMLParserTests.xctest */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 2B6D92351C7F0587000D2D06 /* SwiftyXMLParser */ = {
+ isa = PBXGroup;
+ children = (
+ 2B6D92361C7F0587000D2D06 /* SwiftyXMLParser.h */,
+ 2B6D924D1C7F059B000D2D06 /* XML.swift */,
+ 2B6D924E1C7F059B000D2D06 /* Element.swift */,
+ 2B6D924F1C7F059B000D2D06 /* Accessor.swift */,
+ 2B6D92501C7F059B000D2D06 /* Parser.swift */,
+ 2BD943371CB23CFE007D5FFC /* Error.swift */,
+ 2B6D92381C7F0587000D2D06 /* Info.plist */,
+ );
+ path = SwiftyXMLParser;
+ sourceTree = "";
+ };
+ 2B6D92411C7F0587000D2D06 /* SwiftyXMLParserTests */ = {
+ isa = PBXGroup;
+ children = (
+ 2BD943321CB220FA007D5FFC /* Fixture */,
+ 2B6D92421C7F0587000D2D06 /* SwiftyXMLParserTests.swift */,
+ 2BD9432A1CB220E0007D5FFC /* XMLTests.swift */,
+ 2BD9432C1CB220E5007D5FFC /* ParserTests.swift */,
+ 2BD9432E1CB220EA007D5FFC /* AccessorTests.swift */,
+ 2BD943301CB220F1007D5FFC /* CustomOperatorTests.swift */,
+ 2B6D92441C7F0587000D2D06 /* Info.plist */,
+ );
+ path = SwiftyXMLParserTests;
+ sourceTree = "";
+ };
+ 2BD943321CB220FA007D5FFC /* Fixture */ = {
+ isa = PBXGroup;
+ children = (
+ 2BD943351CB2210D007D5FFC /* XMLDocument.xml */,
+ 2BD943331CB22107007D5FFC /* BrokenXMLDocument.xml */,
+ 2B225AAE1CBCBA40002282BD /* SimpleDocument.xml */,
+ );
+ name = Fixture;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+ 2B6D92301C7F0587000D2D06 /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 2B6D92371C7F0587000D2D06 /* SwiftyXMLParser.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+ 2B6D92321C7F0587000D2D06 /* SwiftyXMLParser */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 2B6D92471C7F0587000D2D06 /* Build configuration list for PBXNativeTarget "SwiftyXMLParser" */;
+ buildPhases = (
+ 2B6D922E1C7F0587000D2D06 /* Sources */,
+ 2B6D922F1C7F0587000D2D06 /* Frameworks */,
+ 2B6D92301C7F0587000D2D06 /* Headers */,
+ 2B6D92311C7F0587000D2D06 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = SwiftyXMLParser;
+ productName = SwiftyXMLParser;
+ productReference = 2B6D92331C7F0587000D2D06 /* SwiftyXMLParser.framework */;
+ productType = "com.apple.product-type.framework";
+ };
+ 2B6D923C1C7F0587000D2D06 /* SwiftyXMLParserTests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 2B6D924A1C7F0587000D2D06 /* Build configuration list for PBXNativeTarget "SwiftyXMLParserTests" */;
+ buildPhases = (
+ 2B6D92391C7F0587000D2D06 /* Sources */,
+ 2B6D923A1C7F0587000D2D06 /* Frameworks */,
+ 2B6D923B1C7F0587000D2D06 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 2B6D92401C7F0587000D2D06 /* PBXTargetDependency */,
+ );
+ name = SwiftyXMLParserTests;
+ productName = SwiftyXMLParserTests;
+ productReference = 2B6D923D1C7F0587000D2D06 /* SwiftyXMLParserTests.xctest */;
+ productType = "com.apple.product-type.bundle.unit-test";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 2B6D922A1C7F0587000D2D06 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastSwiftUpdateCheck = 0720;
+ LastUpgradeCheck = 0720;
+ ORGANIZATIONNAME = "Yahoo! Japan";
+ TargetAttributes = {
+ 2B6D92321C7F0587000D2D06 = {
+ CreatedOnToolsVersion = 7.2.1;
+ };
+ 2B6D923C1C7F0587000D2D06 = {
+ CreatedOnToolsVersion = 7.2.1;
+ };
+ };
+ };
+ buildConfigurationList = 2B6D922D1C7F0587000D2D06 /* Build configuration list for PBXProject "SwiftyXMLParser" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ );
+ mainGroup = 2B6D92291C7F0587000D2D06;
+ productRefGroup = 2B6D92341C7F0587000D2D06 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 2B6D92321C7F0587000D2D06 /* SwiftyXMLParser */,
+ 2B6D923C1C7F0587000D2D06 /* SwiftyXMLParserTests */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 2B6D92311C7F0587000D2D06 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 2B6D923B1C7F0587000D2D06 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 2BD943361CB2210D007D5FFC /* XMLDocument.xml in Resources */,
+ 2B225AAF1CBCBA40002282BD /* SimpleDocument.xml in Resources */,
+ 2BD943341CB22107007D5FFC /* BrokenXMLDocument.xml in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 2B6D922E1C7F0587000D2D06 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 2B6D92541C7F059B000D2D06 /* Parser.swift in Sources */,
+ 2B6D92521C7F059B000D2D06 /* Element.swift in Sources */,
+ 2B6D92511C7F059B000D2D06 /* XML.swift in Sources */,
+ 2BD943381CB23CFE007D5FFC /* Error.swift in Sources */,
+ 2B6D92531C7F059B000D2D06 /* Accessor.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 2B6D92391C7F0587000D2D06 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 2BD943311CB220F1007D5FFC /* CustomOperatorTests.swift in Sources */,
+ 2BD9432F1CB220EA007D5FFC /* AccessorTests.swift in Sources */,
+ 2B6D92431C7F0587000D2D06 /* SwiftyXMLParserTests.swift in Sources */,
+ 2BD9432B1CB220E0007D5FFC /* XMLTests.swift in Sources */,
+ 2BD9432D1CB220E5007D5FFC /* ParserTests.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ 2B6D92401C7F0587000D2D06 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 2B6D92321C7F0587000D2D06 /* SwiftyXMLParser */;
+ targetProxy = 2B6D923F1C7F0587000D2D06 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+ 2B6D92451C7F0587000D2D06 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ CURRENT_PROJECT_VERSION = 1;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 9.2;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VERSIONING_SYSTEM = "apple-generic";
+ VERSION_INFO_PREFIX = "";
+ };
+ name = Debug;
+ };
+ 2B6D92461C7F0587000D2D06 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ CURRENT_PROJECT_VERSION = 1;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 9.2;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ VERSIONING_SYSTEM = "apple-generic";
+ VERSION_INFO_PREFIX = "";
+ };
+ name = Release;
+ };
+ 2B6D92481C7F0587000D2D06 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ENABLE_MODULES = YES;
+ DEFINES_MODULE = YES;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ DYLIB_INSTALL_NAME_BASE = "@rpath";
+ INFOPLIST_FILE = SwiftyXMLParser/Info.plist;
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = jp.co.yahoo.shopping.SwiftyXMLParser;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SKIP_INSTALL = YES;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ };
+ name = Debug;
+ };
+ 2B6D92491C7F0587000D2D06 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ENABLE_MODULES = YES;
+ DEFINES_MODULE = YES;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ DYLIB_INSTALL_NAME_BASE = "@rpath";
+ INFOPLIST_FILE = SwiftyXMLParser/Info.plist;
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = jp.co.yahoo.shopping.SwiftyXMLParser;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SKIP_INSTALL = YES;
+ };
+ name = Release;
+ };
+ 2B6D924B1C7F0587000D2D06 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ INFOPLIST_FILE = SwiftyXMLParserTests/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = jp.co.yahoo.shopping.SwiftyXMLParserTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 2B6D924C1C7F0587000D2D06 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ INFOPLIST_FILE = SwiftyXMLParserTests/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = jp.co.yahoo.shopping.SwiftyXMLParserTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 2B6D922D1C7F0587000D2D06 /* Build configuration list for PBXProject "SwiftyXMLParser" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 2B6D92451C7F0587000D2D06 /* Debug */,
+ 2B6D92461C7F0587000D2D06 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 2B6D92471C7F0587000D2D06 /* Build configuration list for PBXNativeTarget "SwiftyXMLParser" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 2B6D92481C7F0587000D2D06 /* Debug */,
+ 2B6D92491C7F0587000D2D06 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 2B6D924A1C7F0587000D2D06 /* Build configuration list for PBXNativeTarget "SwiftyXMLParserTests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 2B6D924B1C7F0587000D2D06 /* Debug */,
+ 2B6D924C1C7F0587000D2D06 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 2B6D922A1C7F0587000D2D06 /* Project object */;
+}
diff --git a/SwiftyXMLParser.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/SwiftyXMLParser.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100755
index 0000000..6757702
--- /dev/null
+++ b/SwiftyXMLParser.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/SwiftyXMLParser.xcodeproj/project.xcworkspace/xcuserdata/kahayash.xcuserdatad/UserInterfaceState.xcuserstate b/SwiftyXMLParser.xcodeproj/project.xcworkspace/xcuserdata/kahayash.xcuserdatad/UserInterfaceState.xcuserstate
new file mode 100644
index 0000000..569280f
Binary files /dev/null and b/SwiftyXMLParser.xcodeproj/project.xcworkspace/xcuserdata/kahayash.xcuserdatad/UserInterfaceState.xcuserstate differ
diff --git a/SwiftyXMLParser.xcodeproj/xcshareddata/xcschemes/SwiftyXMLParser.xcscheme b/SwiftyXMLParser.xcodeproj/xcshareddata/xcschemes/SwiftyXMLParser.xcscheme
new file mode 100755
index 0000000..51da0db
--- /dev/null
+++ b/SwiftyXMLParser.xcodeproj/xcshareddata/xcschemes/SwiftyXMLParser.xcscheme
@@ -0,0 +1,99 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/SwiftyXMLParser.xcodeproj/xcuserdata/kahayash.xcuserdatad/xcschemes/xcschememanagement.plist b/SwiftyXMLParser.xcodeproj/xcuserdata/kahayash.xcuserdatad/xcschemes/xcschememanagement.plist
new file mode 100755
index 0000000..fe3cda3
--- /dev/null
+++ b/SwiftyXMLParser.xcodeproj/xcuserdata/kahayash.xcuserdatad/xcschemes/xcschememanagement.plist
@@ -0,0 +1,27 @@
+
+
+
+
+ SchemeUserState
+
+ SwiftyXMLParser.xcscheme_^#shared#^_
+
+ orderHint
+ 0
+
+
+ SuppressBuildableAutocreation
+
+ 2B6D92321C7F0587000D2D06
+
+ primary
+
+
+ 2B6D923C1C7F0587000D2D06
+
+ primary
+
+
+
+
+
diff --git a/SwiftyXMLParser/Accessor.swift b/SwiftyXMLParser/Accessor.swift
new file mode 100755
index 0000000..facca11
--- /dev/null
+++ b/SwiftyXMLParser/Accessor.swift
@@ -0,0 +1,442 @@
+/**
+ * The MIT License (MIT)
+ *
+ * Copyright (C) 2016 Yahoo Japan Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+import Foundation
+
+extension XML {
+
+ /**
+ Class for accessing XML Document as SequenceType.
+
+ defined as enumeration which has three states
+ - SingleElement
+ - accesssed the specific XML Element from XML Path
+ - Sequence
+ - accessed multiple Elements from XML Path
+ - Failure
+ - wrong XML Path
+
+
+ */
+ public enum Accessor: CustomStringConvertible, SequenceType {
+ case SingleElement(Element)
+ case Sequence([Element])
+ case Failure(Error)
+
+ public init(_ element: Element) {
+ self = .SingleElement(element)
+ }
+
+ public init(_ sequence: [Element]) {
+ self = .Sequence(sequence)
+ }
+
+ public init(_ error: Error) {
+ self = .Failure(error)
+ }
+
+ /**
+ If Accessor object has a correct XML path, return XML element, otherwith return error
+
+ example:
+
+ ```
+ let hit = xml[1][2][3]
+ ```
+
+
+ The same as:
+ ```
+ let hit = xml[1, 2, 3]
+ ```
+
+ or :
+ ```
+ let path = [1, 2, 3]
+ let hit = xml[path]
+ ```
+
+ */
+ private subscript(index index: Int) -> Accessor {
+ let accessor: Accessor
+ switch self {
+ case .Sequence(let elements) where index < elements.count:
+ accessor = Accessor(elements[index])
+ case .SingleElement(let element) where index == 0:
+ accessor = Accessor(element)
+ case .Failure(let error):
+ accessor = Accessor(error)
+ break
+ default:
+ let error = accessError("cannot access Index: \(index)")
+ accessor = Accessor(error)
+ break
+ }
+ return accessor
+ }
+
+ /**
+ If Accessor object has a correct XML path, return XML element, otherwith return error
+
+ example:
+
+ ```
+ let hit = xml["ResultSet"]["Result"]["Hit"]
+ ```
+
+
+ The same as:
+ ```
+ let hit = xml["ResultSet", "Result", "Hit"]
+ ```
+
+ or :
+ ```
+ let path = ["ResultSet", "Result", "Hit"]
+ let hit = xml[path]
+ ```
+
+ */
+ private subscript(key key: String) -> Accessor {
+ let accessor: Accessor
+ switch self {
+ case .SingleElement(let element):
+ let filterdElements = element.childElements.filter { $0.name == key }
+ if filterdElements.isEmpty {
+ let error = accessError("\(key) not found.")
+ accessor = Accessor(error)
+ } else if filterdElements.count == 1 {
+ accessor = Accessor(filterdElements[0])
+ } else {
+ accessor = Accessor(filterdElements)
+ }
+ case .Failure(let error):
+ accessor = Accessor(error)
+ case .Sequence(_):
+ fallthrough
+ default:
+ let error = accessError("cannot access \(key), because of multiple elements")
+ accessor = Accessor(error)
+ break
+ }
+ return accessor
+ }
+
+ /**
+ If Accessor object has a correct XML path, return XML element, otherwith return error
+
+ example:
+ ```
+ let path = ["ResultSet", "Result", "Hit", 0]
+ let hit = xml[path]
+ ```
+
+ The same as:
+ ```
+ let hit = xml["ResultSet", "Result", "Hit", 0]
+ ```
+
+ or :
+
+ ```
+ let hit = xml["ResultSet"]["Result"]["Hit"][0]
+ ```
+ */
+ public subscript(path: Array) -> Accessor {
+ var accessor = self
+ for position in path {
+ switch position {
+ case let index as Int:
+ accessor = accessor[index]
+ case let key as String:
+ accessor = accessor[key]
+ default:
+ let error = accessError("cannot access \(position)")
+ accessor = Accessor(error)
+ }
+ }
+ return accessor
+ }
+
+ /**
+ If Accessor object has a correct XML path, return XML element, otherwith return error
+
+ example:
+ ```
+ let hit = xml["ResultSet", "Result", "Hit", 0]
+ ```
+
+
+ The same as:
+
+ ```
+ let path = ["ResultSet", "Result", "Hit", 0]
+ let hit = xml[path]
+ ```
+ or :
+
+ ```
+ let hit = xml["ResultSet"]["Result"]["Hit"][0]
+ ```
+ */
+ public subscript(path: XMLSubscriptType...) -> Accessor {
+ var accessor = self
+ for position in path {
+ switch position {
+ case let index as Int:
+ accessor = accessor[index: index]
+ case let key as String:
+ accessor = accessor[key: key]
+ default:
+ let error = accessError("cannot access \(position)")
+ accessor = Accessor(error)
+ }
+ }
+ return accessor
+ }
+
+ public var name: String? {
+ let name: String?
+ switch self {
+ case .SingleElement(let element):
+ name = element.name
+ case .Failure(_), .Sequence(_):
+ fallthrough
+ default:
+ name = nil
+ break
+ }
+ return name
+ }
+
+ public var text: String? {
+ let text: String?
+ switch self {
+ case .SingleElement(let element):
+ text = element.text
+ case .Failure(_), .Sequence(_):
+ fallthrough
+ default:
+ text = nil
+ break
+ }
+ return text
+ }
+
+
+ /// syntax sugar to access Bool Text
+ public var bool: Bool? {
+ return text.flatMap { $0 == "true" }
+ }
+
+
+ /// syntax sugar to access URL Text
+ public var url: NSURL? {
+ return text.flatMap({NSURL(string: $0)})
+ }
+
+ /// syntax sugar to access Int Text
+ public var int: Int? {
+ return text.flatMap({Int($0)})
+ }
+
+ /// syntax sugar to access Double Text
+ public var double: Double? {
+ return text.flatMap({Double($0)})
+ }
+
+ /// access to XML Attributes
+ public var attributes: [String: String] {
+ let attributes: [String: String]
+ switch self {
+ case .SingleElement(let element):
+ attributes = element.attributes
+ case .Failure(_), .Sequence(_):
+ fallthrough
+ default:
+ attributes = [String: String]()
+ break
+ }
+ return attributes
+ }
+
+ /// access to child Elements
+ public var all: [Element]? {
+ switch self {
+ case .SingleElement(let element):
+ return [element]
+ case .Sequence(let elements):
+ return elements
+ case .Failure(_):
+ return nil
+ }
+ }
+
+ /// access to child Elemnet Tag Names
+ public var names: [String]? {
+ switch self {
+ case .SingleElement(let element):
+ return [element.name]
+ case .Sequence(let elements):
+ return elements.map { $0.name }
+ case .Failure(_):
+ return nil
+ }
+ }
+
+ /// if it has wrong XML path, return Error, otherwise return nil
+ public var error: Error? {
+ switch self {
+ case .Failure(let error):
+ return error
+ case .SingleElement(_), .Sequence(_):
+ return nil
+ }
+ }
+
+
+ /// if it has wrong XML path or multiple child elements, return nil, otherwise return Element
+ public var element: Element? {
+ switch self {
+ case .SingleElement(let element):
+ return element
+ case .Failure(_), .Sequence(_):
+ return nil
+ }
+ }
+
+ /// if it has wrong XML path or no child Element, return nil, otherwise return last Element
+ public var last: Accessor {
+ switch self {
+ case .SingleElement(let element):
+ return Accessor(element)
+ case .Sequence(let elements):
+ if let lastElement = elements.last {
+ return Accessor(lastElement)
+ } else {
+ return Accessor(accessError("cannot access last element"))
+ }
+ case .Failure(let error):
+ return Accessor(error)
+ }
+ }
+
+ /// if it has wrong XML path or no child Element, return nil, otherwise return first Element
+ public var first: Accessor {
+ switch self {
+ case .SingleElement(let element):
+ return Accessor(element)
+ case .Sequence(let elements):
+ if let firstElement = elements.first {
+ return Accessor(firstElement)
+ } else {
+ return Accessor(accessError("cannot access first element"))
+ }
+ case .Failure(let error):
+ return Accessor(error)
+ }
+ }
+
+ public func map(transform: (Accessor) -> T) -> [T] {
+ switch self {
+ case .SingleElement(let element):
+ return [Accessor(element)].map(transform)
+ case .Sequence(let elements):
+ return elements.map({ Accessor($0) }).map(transform)
+ case .Failure:
+ return [Accessor]().map(transform)
+ }
+ }
+
+ @available(*, renamed="flatMap")
+ public func mapWithSqueezeNil(transform: (Accessor) -> T?) -> [T] {
+ var accessors = [Accessor]()
+ switch self {
+ case .SingleElement(let element):
+ accessors = [Accessor(element)]
+ case .Sequence(let elements):
+ accessors = elements.map({ Accessor($0) })
+ case .Failure:
+ accessors = [Accessor]()
+ }
+ return accessors.reduce([T]()) {
+ let transformed = transform($1)
+ if let unwrappedTransform = transformed {
+ return $0 + [unwrappedTransform]
+ } else {
+ return $0
+ }
+ }
+ }
+
+ // MARK :- SequenceType
+
+ public func generate() -> AnyGenerator {
+ let generator: [Element]
+ switch self {
+ case .Failure(_):
+ generator = [Element]()
+ case .SingleElement(let element):
+ generator = [element]
+ case .Sequence(let elements):
+ generator = elements
+ }
+ var index = 0
+ return anyGenerator {
+ if index < generator.count {
+ return Accessor(generator[index++])
+ } else {
+ return nil
+ }
+ }
+ }
+
+
+ // MARK: - CustomStringConvertible
+
+ public var description: String {
+ switch self {
+ case .SingleElement(let element):
+ return "\"" + self.recursivePrintAncient(element) + "\""
+ case .Sequence(let elements):
+ let descriptions = elements.map { self.recursivePrintAncient($0) }
+ return "[ " + descriptions.joinWithSeparator(",\n ") + " ]"
+ case .Failure(let error):
+ return "\(error)"
+ }
+ }
+
+ private func recursivePrintAncient(element: Element) -> String {
+ var description = element.name
+ if let unwrappedParent = element.parentElement {
+ description = recursivePrintAncient(unwrappedParent) + " > " + description
+ }
+ return description
+ }
+
+ private func accessError(description: String) -> Error {
+ return Error.AccessError(description: description)
+ }
+ }
+}
diff --git a/SwiftyXMLParser/Element.swift b/SwiftyXMLParser/Element.swift
new file mode 100755
index 0000000..fc62498
--- /dev/null
+++ b/SwiftyXMLParser/Element.swift
@@ -0,0 +1,41 @@
+/**
+ * The MIT License (MIT)
+ *
+ * Copyright (C) 2016 Yahoo Japan Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+import Foundation
+
+extension XML {
+ public class Element {
+ public var name: String
+ public var text: String?
+ public var attributes = [String: String]()
+ public var childElements = [Element]()
+
+ // for println
+ public weak var parentElement: Element?
+
+ public init(name: String) {
+ self.name = name
+ }
+ }
+}
\ No newline at end of file
diff --git a/SwiftyXMLParser/Error.swift b/SwiftyXMLParser/Error.swift
new file mode 100755
index 0000000..5c05d8a
--- /dev/null
+++ b/SwiftyXMLParser/Error.swift
@@ -0,0 +1,32 @@
+/**
+ * The MIT License (MIT)
+ *
+ * Copyright (C) 2016 Yahoo Japan Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+import Foundation
+
+extension XML {
+ public enum Error: ErrorType {
+ case ParseError
+ case AccessError(description: String)
+ }
+}
\ No newline at end of file
diff --git a/SwiftyXMLParser/Info.plist b/SwiftyXMLParser/Info.plist
new file mode 100755
index 0000000..d3de8ee
--- /dev/null
+++ b/SwiftyXMLParser/Info.plist
@@ -0,0 +1,26 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ FMWK
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ $(CURRENT_PROJECT_VERSION)
+ NSPrincipalClass
+
+
+
diff --git a/SwiftyXMLParser/Parser.swift b/SwiftyXMLParser/Parser.swift
new file mode 100755
index 0000000..8211d65
--- /dev/null
+++ b/SwiftyXMLParser/Parser.swift
@@ -0,0 +1,79 @@
+/**
+ * The MIT License (MIT)
+ *
+ * Copyright (C) 2016 Yahoo Japan Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+import Foundation
+
+extension XML {
+ class Parser: NSObject, NSXMLParserDelegate {
+ func parse(data: NSData) -> Accessor {
+ stack = [Element]()
+ stack.append(documentRoot)
+ let parser = NSXMLParser(data: data)
+ parser.delegate = self
+ parser.parse()
+ return Accessor(documentRoot)
+ }
+
+ override init() {
+ trimmingManner = nil
+ }
+
+ init(trimming manner: NSCharacterSet) {
+ trimmingManner = manner
+ }
+
+ // MARK:- private
+ private var documentRoot = Element(name: "XML.Parser.AbstructedDocumentRoot")
+ private var stack = [Element]()
+ private let trimmingManner: NSCharacterSet?
+
+ func parser(parser: NSXMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {
+ let node = Element(name: elementName)
+ if !attributeDict.isEmpty {
+ node.attributes = attributeDict
+ }
+
+ let parentNode = stack.last
+
+ node.parentElement = parentNode
+ parentNode?.childElements.append(node)
+ stack.append(node)
+ }
+
+ func parser(parser: NSXMLParser, foundCharacters string: String) {
+ if let text = stack.last?.text {
+ stack.last?.text = text + (string ?? "")
+ } else {
+ stack.last?.text = "" + (string ?? "")
+ }
+ }
+
+ func parser(parser: NSXMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
+ if let trimmingManner = self.trimmingManner {
+ stack.last?.text = stack.last?.text?.stringByTrimmingCharactersInSet(trimmingManner)
+ }
+ stack.removeLast()
+ }
+ }
+}
\ No newline at end of file
diff --git a/SwiftyXMLParser/SwiftyXMLParser.h b/SwiftyXMLParser/SwiftyXMLParser.h
new file mode 100755
index 0000000..b2f05f0
--- /dev/null
+++ b/SwiftyXMLParser/SwiftyXMLParser.h
@@ -0,0 +1,35 @@
+/**
+ * The MIT License (MIT)
+ *
+ * Copyright (C) 2016 Yahoo Japan Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#import
+
+//! Project version number for SwiftyXMLParser.
+FOUNDATION_EXPORT double SwiftyXMLParserVersionNumber;
+
+//! Project version string for SwiftyXMLParser.
+FOUNDATION_EXPORT const unsigned char SwiftyXMLParserVersionString[];
+
+// In this header, you should import all the public headers of your framework using statements like #import
+
+
diff --git a/SwiftyXMLParser/XML.swift b/SwiftyXMLParser/XML.swift
new file mode 100755
index 0000000..738069e
--- /dev/null
+++ b/SwiftyXMLParser/XML.swift
@@ -0,0 +1,138 @@
+/**
+ * The MIT License (MIT)
+ *
+ * Copyright (C) 2016 Yahoo Japan Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+import Foundation
+
+/// available Type in XML.Accessor subscript
+public protocol XMLSubscriptType {}
+extension Int: XMLSubscriptType {}
+extension String: XMLSubscriptType {}
+
+infix operator ?= {} // Failable Assignment
+
+/**
+ assign value if rhs is not optonal. When rhs is optional, nothing to do.
+*/
+public func ?=(inout lhs: T, rhs: T?) {
+ if let unwrappedRhs = rhs {
+ lhs = unwrappedRhs
+ }
+}
+
+infix operator ?<< {} // Failable Push
+
+/**
+ push value to array if rhs is not optonal. When rhs is optional, nothing to do.
+*/
+public func ?<< (inout lhs: [T], rhs: T?) {
+ if let unwrappedRhs = rhs {
+ lhs.append(unwrappedRhs)
+ }
+}
+
+
+/**
+ Director class to parse and access XML document.
+
+ You can parse XML docuemnts with parse() method and get the accessor.
+
+ ### Example
+ ```
+ let string = "ほげふが"
+ xml = XML.parse(string)
+ let text = xml["ResultSet"]["Result"]["Hit"][0]["Name"].text {
+ println("exsists path & text")
+ }
+
+ let text = xml["ResultSet", "Result", "Hit", 0, "Name"].text {
+ println("exsists path & text")
+ }
+
+ let attributes = xml["ResultSet", "Result", "Hit", 0, "Name"].attributes {
+ println("exsists path & attributes")
+ }
+
+ for hit in xml["ResultSet", "Result", "Hit"] {
+ println("enumarate existing element")
+ }
+
+ switch xml["ResultSet", "Result", "TypoKey"] {
+ case .Failure(let error):
+ println(error)
+ case .SingleElement(_), .Sequence(_):
+ println("success parse")
+ }
+ ```
+*/
+public class XML {
+ /**
+ Interface to parse NSData
+
+ - parameter data:NSData XML document
+ - returns:Accessor object to access XML document
+ */
+ public class func parse(data: NSData) -> Accessor {
+ return Parser().parse(data)
+ }
+
+ /**
+ Interface to parse String
+
+ - Parameter str:String XML document
+ - Returns:Accessor object to access XML document
+ */
+ public class func parse(str: String) throws -> Accessor {
+ guard let data = str.dataUsingEncoding(NSUTF8StringEncoding) else {
+ throw XML.Error.ParseError
+ }
+
+ return Parser().parse(data)
+ }
+
+ /**
+ Interface to parse NSData
+
+ - parameter data:NSData XML document
+ - parameter manner:NSCharacterSet If you wannna trim Text, assign this arg
+ - returns:Accessor object to access XML document
+ */
+ public class func parse(data: NSData, trimming manner: NSCharacterSet) -> Accessor {
+ return Parser(trimming: manner).parse(data)
+ }
+
+ /**
+ Interface to parse String
+
+ - Parameter str:String XML document
+ - parameter manner:NSCharacterSet If you wannna trim Text, assign this arg
+ - Returns:Accessor object to access XML document
+ */
+ public class func parse(str: String, trimming manner: NSCharacterSet) throws -> Accessor {
+ guard let data = str.dataUsingEncoding(NSUTF8StringEncoding) else {
+ throw XML.Error.ParseError
+ }
+
+ return Parser(trimming: manner).parse(data)
+ }
+}
\ No newline at end of file
diff --git a/SwiftyXMLParserTests/AccessorTests.swift b/SwiftyXMLParserTests/AccessorTests.swift
new file mode 100755
index 0000000..53253d0
--- /dev/null
+++ b/SwiftyXMLParserTests/AccessorTests.swift
@@ -0,0 +1,404 @@
+/**
+ * The MIT License (MIT)
+ *
+ * Copyright (C) 2016 Yahoo Japan Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+import UIKit
+import XCTest
+@testable import SwiftyXMLParser
+
+class AccessorTests: XCTestCase {
+
+ override func setUp() {
+ super.setUp()
+ }
+
+ override func tearDown() {
+ super.tearDown()
+ }
+
+ func testIndexerTypeIntToSingleElement() {
+ let singleElementAccessor = XML.Accessor(singleElement())
+ let target1 = singleElementAccessor[0]
+ if let name = target1.name {
+ XCTAssertEqual(name, "RootElement", "can access element name")
+ } else {
+ XCTFail("fail to get name")
+ }
+
+ let target2 = singleElementAccessor[1]
+ switch target2 {
+ case .Failure(_):
+ XCTAssert(true, "access to wrong path")
+ default:
+ XCTFail("need to fail")
+ }
+ }
+
+ func testIndexerTypeIntToSequence() {
+ let accessor = XML.Accessor(sequence())
+ let target1 = accessor[0]
+ if let name = target1.name {
+ XCTAssertEqual(name, "Element", "can access corrent element")
+ } else {
+ XCTFail("fail to get name")
+ }
+
+ let target2 = accessor[1]
+ if let name = target2.name {
+ XCTAssertEqual(name, "Element", "can access corrent element")
+ } else {
+ XCTFail("fail to get name")
+ }
+
+ let target3 = accessor[2]
+ switch target3 {
+ case .Failure(_):
+ XCTAssert(true, "Aaccess to wrong path")
+ default:
+ XCTFail("need to fail")
+ }
+ }
+
+ func testIndexerTypeString() {
+ let accessor = XML.Accessor(singleElement())
+ let me = accessor["RootElement"]
+ switch me {
+ case .Failure(_):
+ XCTAssert(true, "can access corrent element")
+ default:
+ XCTFail("fail to get element")
+ }
+ }
+
+ func testIndexerTypeStringShingleElement() {
+ let accessor = XML.Accessor(singleElement())
+ let children = accessor["ChildElement"]
+ switch children {
+ case .Sequence(_):
+ XCTAssert(true, "can access corrent element")
+ default:
+ XCTFail("fail to get element")
+ }
+ }
+
+ func testIndexerTypeStringSequence() {
+ let accessor = XML.Accessor(sequence())
+ let failureChildren = accessor["ChildElement"]
+ switch failureChildren {
+ case .Failure(_):
+ XCTAssert(true, "need to select one element from multiple elements")
+ default:
+ XCTFail("need to fail")
+ }
+
+ let successChildren = accessor[0]["ChildElement1"]
+ switch successChildren {
+ case .Sequence(_):
+ XCTAssert(true, "can access corrent element")
+ default:
+ XCTFail("fail to get element")
+ }
+ }
+
+ func testIndexerToFailure() {
+ let accessor = XML.Accessor(failure())
+ let intIndexer = accessor[0]
+ switch intIndexer {
+ case .Failure(_):
+ XCTAssert(true, "need to return failure when access wrong path once")
+ default:
+ XCTFail("need to fail")
+ }
+
+ let stringIndexer = accessor["ChildElement"]
+ switch stringIndexer {
+ case .Failure(_):
+ XCTAssert(true, "need to return failure when access wrong path once")
+ default:
+ XCTFail("need to fail")
+ }
+ }
+
+ func testIndexTypeArray() {
+ let accessor = XML.Accessor(sequence())
+ let indexer = accessor[[0, "ChildElement1", 1]]
+ switch indexer {
+ case .SingleElement(_):
+ XCTAssert(true, "access element with Array")
+ default:
+ XCTFail("fail to get element")
+ }
+
+ let failureIndexer = accessor[[1, "Hoget", "Foge"]]
+ switch failureIndexer {
+ case .Failure(_):
+ XCTAssert(true, "access wrong path with Array")
+ default:
+ XCTFail("need to fail")
+ }
+ }
+
+ func testIndexTypeVariableArguments() {
+ let accessor = XML.Accessor(sequence())
+ let indexer = accessor[0, "ChildElement1", 1]
+ switch indexer {
+ case .SingleElement(_):
+ XCTAssert(true, "access element with Variadic")
+ default:
+ XCTFail("fail to get element")
+ }
+
+ let failureIndexer = accessor[1, "Hoget", "Foge"]
+ switch failureIndexer {
+ case .Failure(_):
+ XCTAssert(true, "access wrong path with Variadic")
+ default:
+ XCTFail("need to fail")
+ }
+ }
+
+ func testName() {
+ let accessor = XML.Accessor(singleElement())
+ if let name = accessor.name {
+ XCTAssertEqual(name, "RootElement", "access name with SingleElement Accessor")
+ } else {
+ XCTFail("fail")
+ }
+
+ let sequenceAccessor = XML.Accessor(sequence())
+ if let _ = sequenceAccessor.name {
+ XCTFail("access name with Failure Sequence")
+ } else {
+ XCTAssert(true, "fail")
+ }
+
+ let failureAccessor = XML.Accessor(failure())
+ if let _ = failureAccessor.name {
+ XCTFail("fail")
+ } else {
+ XCTAssert(true, "fail to access name with Failure Accessor")
+ }
+ }
+
+ func testText() {
+ let accessor = XML.Accessor(singleElement())
+ if let text = accessor.text {
+ XCTAssertEqual(text, "text", "access text with SingleElement Accessor")
+ } else {
+ XCTFail("fail")
+ }
+
+ let sequenceAccessor = XML.Accessor(sequence())
+ if let _ = sequenceAccessor.text {
+ XCTFail("fail")
+ } else {
+ XCTAssert(true, "fail to access text with Sequence Accessor")
+ }
+
+ let failureAccessor = XML.Accessor(failure())
+ if let _ = failureAccessor.text {
+ XCTFail("fail")
+ } else {
+ XCTAssert(true, "fail to access name with Failure Accessor")
+ }
+ }
+
+ func testAttributes() {
+ let accessor = XML.Accessor(singleElement())
+ if !accessor.attributes.isEmpty {
+ XCTAssertEqual(accessor.attributes, ["key": "value"], "access attriubtes with SingleElement Accessor")
+ } else {
+ XCTFail("fail")
+ }
+
+ let sequenceAccessor = XML.Accessor(sequence())
+ if !sequenceAccessor.attributes.isEmpty {
+ XCTFail("fail")
+ } else {
+ XCTAssert(true, "fail to attributes text with Sequence Accessor")
+ }
+
+ let failureAccessor = XML.Accessor(failure())
+ if !failureAccessor.attributes.isEmpty {
+ XCTFail("fail")
+ } else {
+ XCTAssert(true, "fail to access name with Failure Accessor")
+ }
+ }
+
+ func testAll() {
+ let accessor = XML.Accessor(singleElement())
+ if let all = accessor.all {
+ XCTAssertEqual(all.count, 1, "access all elements")
+ } else {
+ XCTFail("fail")
+ }
+
+ let sequenceAccessor = XML.Accessor(sequence())
+ if let all = sequenceAccessor.all {
+ XCTAssertEqual(all.count, 2, "access all elements")
+ } else {
+ XCTAssert(true, "fail")
+ }
+
+ let failureAccessor = XML.Accessor(failure())
+ if let _ = failureAccessor.all {
+ XCTFail("access all elements")
+ } else {
+ XCTAssert(true, "fail")
+ }
+ }
+
+ func testNames() {
+ let accessor = XML.Accessor(singleElement())
+ if let names = accessor.names {
+ XCTAssertEqual(names[0], "RootElement", "access all names")
+ } else {
+ XCTFail("fail")
+ }
+
+ let sequenceAccessor = XML.Accessor(sequence())
+ if let names = sequenceAccessor.names {
+ XCTAssertEqual(names, ["Element", "Element"], "access all names")
+ } else {
+ XCTFail("fail")
+ }
+
+ let failureAccessor = XML.Accessor(failure())
+ if let _ = failureAccessor.names {
+ XCTFail("fail")
+ } else {
+ XCTAssert(true, "fail to access all names")
+ }
+ }
+
+ func testError() {
+ let accessor = XML.Accessor(singleElement())
+ if let _ = accessor.error {
+ XCTFail("fail")
+ } else {
+ XCTAssert(true, "return nil from SngleElement")
+
+ }
+
+ let sequenceAccessor = XML.Accessor(sequence())
+ if let _ = sequenceAccessor.error {
+ XCTFail("fail")
+ } else {
+ XCTAssert(true, "return nil from SngleElement")
+
+ }
+
+ let failureAccessor = XML.Accessor(failure())
+ if let _ = failureAccessor.error {
+ XCTAssert(true, "return Error from SngleElement")
+ } else {
+ XCTFail("fail")
+ }
+ }
+
+ func testMap() {
+ let accessor = XML.Accessor(singleElement())
+ let newAccessor = accessor.map { $0 }
+ XCTAssertEqual(newAccessor.count, 1, "access single element with map")
+
+ let sequenceAccessor = XML.Accessor(sequence())
+ let newSequenceAccessor = sequenceAccessor.map { $0 }
+ XCTAssertEqual(newSequenceAccessor.count, 2, "access each element with map")
+
+ let failureAccessor = XML.Accessor(failure())
+ let newFailureAccessor = failureAccessor.map { $0 }
+ XCTAssertEqual(newFailureAccessor.count, 0, "access failure with map")
+ }
+
+ func testFlatMap() {
+ let accessor = XML.Accessor(singleElement())
+ let singleText = accessor.flatMap { $0.text }
+ XCTAssertEqual(singleText, ["text"], "can access text")
+
+ let sequenceAccessor = XML.Accessor(sequence())
+ let texts = sequenceAccessor.flatMap { $0.text }
+ XCTAssertEqual(texts, ["text", "text2"], "can access each text")
+
+ let failureAccessor = XML.Accessor(failure())
+ let failureTexts = failureAccessor.flatMap { $0.text }
+ XCTAssertEqual(failureTexts, [], "has no text")
+ }
+
+
+ func testIterator() {
+ let accessor = XML.Accessor(singleElement())
+ var result: [XML.Accessor] = []
+ for accessorElem in accessor {
+ result.append(accessorElem)
+ }
+ XCTAssertEqual(result.count, 1, "access single element with for-in")
+
+ let sequneceAccessor = XML.Accessor(sequence())
+ var sequenceResult: [XML.Accessor] = []
+ for accessorElem in sequneceAccessor {
+ sequenceResult.append(accessorElem)
+ }
+ XCTAssertEqual(sequenceResult.count, 2, "access multiple element with for-in")
+
+ let failureAccessor = XML.Accessor(failure())
+ var failureResult: [XML.Accessor] = []
+ for accessorElem in failureAccessor {
+ failureResult.append(accessorElem)
+ }
+ XCTAssertEqual(failureResult.count, 0, "access failure element with for-in")
+ }
+
+ private func singleElement() -> XML.Element {
+ let element = XML.Element(name: "RootElement")
+ element.text = "text"
+ element.attributes = ["key": "value"]
+ element.childElements = [
+ XML.Element(name: "ChildElement"),
+ XML.Element(name: "ChildElement")
+ ]
+ return element
+ }
+
+ private func sequence() -> [XML.Element] {
+ let elem1 = XML.Element(name: "Element")
+ elem1.text = "text"
+ elem1.attributes = ["key": "value"]
+ elem1.childElements = [
+ XML.Element(name: "ChildElement1"),
+ XML.Element(name: "ChildElement1")
+ ]
+ let elem2 = XML.Element(name: "Element")
+ elem2.text = "text2"
+ elem2.childElements = [
+ XML.Element(name: "ChildElement2"),
+ XML.Element(name: "ChildElement2")
+ ]
+ let elements = [ elem1, elem2 ]
+ return elements
+ }
+
+ private func failure() -> XML.Error {
+ return XML.Error.AccessError(description: "error")
+ }
+}
diff --git a/SwiftyXMLParserTests/BrokenXMLDocument.xml b/SwiftyXMLParserTests/BrokenXMLDocument.xml
new file mode 100755
index 0000000..f3c7dfd
--- /dev/null
+++ b/SwiftyXMLParserTests/BrokenXMLDocument.xml
@@ -0,0 +1,8 @@
+
+
+
+
+ ノートパソコン
+ 送料無料!延長保証受付中!
+ 14型ワイド ノートPC
+
\ No newline at end of file
diff --git a/SwiftyXMLParserTests/CustomOperatorTests.swift b/SwiftyXMLParserTests/CustomOperatorTests.swift
new file mode 100755
index 0000000..db6b47f
--- /dev/null
+++ b/SwiftyXMLParserTests/CustomOperatorTests.swift
@@ -0,0 +1,55 @@
+/**
+ * The MIT License (MIT)
+ *
+ * Copyright (C) 2016 Yahoo Japan Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+import UIKit
+import XCTest
+@testable import SwiftyXMLParser
+
+class CustomOperatorTests: XCTestCase {
+
+ override func setUp() {
+ super.setUp()
+ // Put setup code here. This method is called before the invocation of each test method in the class.
+ }
+
+ override func tearDown() {
+ // Put teardown code here. This method is called after the invocation of each test method in the class.
+ super.tearDown()
+ }
+
+ // MAKR:- ?=のテスト
+ func testFailableAssignment() {
+ let optionalSome: Int? = 1
+ var targetSome: Int = 0
+ targetSome ?= optionalSome
+ XCTAssertEqual(targetSome, 1, "assign if not Optional")
+
+
+ let optionalNone: Int? = nil
+ var targetNone: Int = 0
+ targetNone ?= optionalNone
+ XCTAssertEqual(targetNone, 0, "go through if Optional")
+ }
+
+}
diff --git a/SwiftyXMLParserTests/Info.plist b/SwiftyXMLParserTests/Info.plist
new file mode 100755
index 0000000..ba72822
--- /dev/null
+++ b/SwiftyXMLParserTests/Info.plist
@@ -0,0 +1,24 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ BNDL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 1
+
+
diff --git a/SwiftyXMLParserTests/ParserTests.swift b/SwiftyXMLParserTests/ParserTests.swift
new file mode 100755
index 0000000..861c14d
--- /dev/null
+++ b/SwiftyXMLParserTests/ParserTests.swift
@@ -0,0 +1,148 @@
+/**
+ * The MIT License (MIT)
+ *
+ * Copyright (C) 2016 Yahoo Japan Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+import UIKit
+import XCTest
+@testable import SwiftyXMLParser
+
+
+class ParserTests: XCTestCase {
+
+ override func setUp() {
+ super.setUp()
+ }
+
+ override func tearDown() {
+ super.tearDown()
+ }
+
+ func testSuccessParse() {
+ guard let path = NSBundle(forClass: self.dynamicType).pathForResource("XMLDocument", ofType: "xml"),
+ let data = NSData(contentsOfFile: path) else {
+ XCTFail("fail to parse")
+ return
+ }
+
+ let xml = XML.Parser().parse(data)
+ if let _ = xml["ResultSet"].error {
+ XCTFail("fail to parse")
+ } else {
+ XCTAssert(true, "success to parse")
+ }
+
+
+ }
+
+ func testFailParse() {
+ guard let path = NSBundle(forClass: self.dynamicType).pathForResource("BrokenXMLDocument", ofType: "xml"),
+ let data = NSData(contentsOfFile: path) else {
+ XCTFail("fail to parse")
+ return
+ }
+
+ let xml = XML.Parser().parse(data)
+ if let _ = xml["ResultSet"].error {
+ XCTFail("fail to parse")
+ } else {
+ XCTAssert(true, "success to parse")
+ }
+ }
+
+ func testTextParseWithMockData() {
+ guard let path = NSBundle(forClass: self.dynamicType).pathForResource("SimpleDocument", ofType: "xml"),
+ let data = NSData(contentsOfFile: path) else {
+ XCTFail("fail to parse")
+ return
+ }
+
+ let xml = XML.Parser().parse(data)
+ if let text = xml["Result", "Text"].text {
+ XCTAssertEqual("Text", text, "Parsed Text")
+ } else {
+ XCTAssert(true, "fail to parse")
+ }
+ }
+
+ func testWhitespaceParseWithMockData() {
+ guard let path = NSBundle(forClass: self.dynamicType).pathForResource("SimpleDocument", ofType: "xml"),
+ let data = NSData(contentsOfFile: path) else {
+ XCTFail("fail to parse")
+ return
+ }
+
+ let xml = XML.Parser().parse(data)
+ if let text = xml["Result", "Whitespace"].text {
+ XCTAssertEqual(" ", text, "Parsed Single-Bite Whitespace")
+ } else {
+ XCTFail("fail")
+ }
+ }
+
+ func testReturnParseWithMockData() {
+ guard let path = NSBundle(forClass: self.dynamicType).pathForResource("SimpleDocument", ofType: "xml"),
+ let data = NSData(contentsOfFile: path) else {
+ XCTFail("fail to parse")
+ return
+ }
+
+ let xml = XML.Parser().parse(data)
+ if let text = xml["Result", "OnlyReturn"].text {
+ XCTAssertEqual("\n", text, "Parsed line break code")
+ } else {
+ XCTAssert(false, "need to have no line break code")
+ }
+ }
+
+ func testWhitespaceAndReturnParseWithMockData() {
+ guard let path = NSBundle(forClass: self.dynamicType).pathForResource("SimpleDocument", ofType: "xml"),
+ let data = NSData(contentsOfFile: path) else {
+ XCTFail("fail to parse")
+ return
+ }
+
+ let xml = XML.Parser().parse(data)
+ if let text = xml["Result", "WhitespaceReturn"].text {
+ XCTAssertEqual("\n \n", text, "Parsed whitespace and line break code")
+ } else {
+ XCTAssert(false, "need to have no line break code")
+
+ }
+ }
+
+ func testWhitespaceAndReturnParseWithMockDataAndTrimmingWhitespaceAndLineBreak() {
+ guard let path = NSBundle(forClass: self.dynamicType).pathForResource("SimpleDocument", ofType: "xml"),
+ let data = NSData(contentsOfFile: path) else {
+ XCTFail("fail to parse")
+ return
+ }
+
+
+ let xml = XML.Parser(trimming: .whitespaceAndNewlineCharacterSet()).parse(data)
+ if let text = xml["Result", "WhitespaceReturn"].text {
+ XCTAssertEqual("", text, "Parsed Success and trim them")
+ } else {
+ XCTAssert(false, "fail")
+ }
+ }
+}
\ No newline at end of file
diff --git a/SwiftyXMLParserTests/SimpleDocument.xml b/SwiftyXMLParserTests/SimpleDocument.xml
new file mode 100755
index 0000000..c09b7cf
--- /dev/null
+++ b/SwiftyXMLParserTests/SimpleDocument.xml
@@ -0,0 +1,7 @@
+
+ Text
+
+
+
+
+
\ No newline at end of file
diff --git a/SwiftyXMLParserTests/SwiftyXMLParserTests.swift b/SwiftyXMLParserTests/SwiftyXMLParserTests.swift
new file mode 100755
index 0000000..f6eb335
--- /dev/null
+++ b/SwiftyXMLParserTests/SwiftyXMLParserTests.swift
@@ -0,0 +1,52 @@
+/**
+ * The MIT License (MIT)
+ *
+ * Copyright (C) 2016 Yahoo Japan Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+import XCTest
+@testable import SwiftyXMLParser
+
+class SwiftyXMLParserTests: XCTestCase {
+
+ override func setUp() {
+ super.setUp()
+ // Put setup code here. This method is called before the invocation of each test method in the class.
+ }
+
+ override func tearDown() {
+ // Put teardown code here. This method is called after the invocation of each test method in the class.
+ super.tearDown()
+ }
+
+ func testExample() {
+ // This is an example of a functional test case.
+ // Use XCTAssert and related functions to verify your tests produce the correct results.
+ }
+
+ func testPerformanceExample() {
+ // This is an example of a performance test case.
+ self.measureBlock {
+ // Put the code you want to measure the time of here.
+ }
+ }
+
+}
diff --git a/SwiftyXMLParserTests/XMLDocument.xml b/SwiftyXMLParserTests/XMLDocument.xml
new file mode 100755
index 0000000..871c5d7
--- /dev/null
+++ b/SwiftyXMLParserTests/XMLDocument.xml
@@ -0,0 +1,20 @@
+
+
+
+
+ ノートパソコン
+ 送料無料!延長保証受付中!
+ 14型ワイド ノートPC
+
+
+ ノートパソコン
+ 送料無料!延長保証受付中!
+ 14型ワイド ノートPC
+
+
+ ノートパソコン
+ 送料無料!延長保証受付中!
+ 14型ワイド ノートPC
+
+
+
\ No newline at end of file
diff --git a/SwiftyXMLParserTests/XMLTests.swift b/SwiftyXMLParserTests/XMLTests.swift
new file mode 100755
index 0000000..61a309f
--- /dev/null
+++ b/SwiftyXMLParserTests/XMLTests.swift
@@ -0,0 +1,86 @@
+/**
+ * The MIT License (MIT)
+ *
+ * Copyright (C) 2016 Yahoo Japan Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+import UIKit
+import XCTest
+@testable import SwiftyXMLParser
+
+class XMLTests: XCTestCase {
+
+ override func setUp() {
+ super.setUp()
+ }
+
+ override func tearDown() {
+ super.tearDown()
+ }
+
+ func testParse() {
+ if let path = NSBundle(forClass: self.dynamicType).pathForResource("XMLDocument", ofType: "xml") {
+ if let data = NSData(contentsOfFile: path) {
+ let xml = XML.parse(data)
+ if let _ = xml["ResultSet"].error {
+ XCTFail("fail to parse")
+
+ } else {
+ XCTAssert(true, "sucess to Parse")
+ }
+ } else {
+ XCTFail("fail to generate data")
+ }
+ } else {
+ XCTFail("fail to parse")
+ }
+ }
+
+
+ func testSuccessParseFromString() {
+ if let path = NSBundle(forClass: self.dynamicType).pathForResource("XMLDocument", ofType: "xml"),
+ let string = try? String(contentsOfFile: path, encoding: NSUTF8StringEncoding),
+ let xml = try? XML.parse(string) {
+ if let _ = xml["ResultSet"].error {
+ XCTFail("fail to parse")
+ } else {
+ XCTAssert(true, "success to parse")
+ }
+ } else {
+ XCTFail("fail to parse")
+ }
+ }
+
+
+ func testSuccessParseFromDoublebyteSpace() {
+ guard let xml = try? XML.parse(" ") else {
+ XCTFail("Fail Prase")
+ return
+ }
+
+ if let name = xml["Name"].text {
+ XCTAssertEqual(name, " ", "Parse Success Double-byte Space")
+ } else {
+ XCTFail("Fail Prase")
+ }
+ }
+
+}