mirror of
https://github.com/exyte/Macaw.git
synced 2024-09-11 13:15:35 +03:00
Merge pull request #772 from exyte/769-SWXMLHash-Compatibility
#769 SWXMLHash Compatibility
This commit is contained in:
commit
b332010acd
392
Dependencies/SWXMLHash/SWXMLHash.swift → Dependencies/SWXMLHash/XMLHash.swift
vendored
Executable file → Normal file
392
Dependencies/SWXMLHash/SWXMLHash.swift → Dependencies/SWXMLHash/XMLHash.swift
vendored
Executable file → Normal file
@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// SWXMLHash.swift
|
// XMLHash.swift
|
||||||
// SWXMLHash
|
// SWXMLHash
|
||||||
//
|
//
|
||||||
// Copyright (c) 2014 David Mohundro
|
// Copyright (c) 2014 David Mohundro
|
||||||
@ -30,11 +30,14 @@
|
|||||||
// swiftlint:disable file_length
|
// swiftlint:disable file_length
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
#if canImport(FoundationXML)
|
||||||
|
import FoundationXML
|
||||||
|
#endif
|
||||||
|
|
||||||
let rootElementName = "SWXMLHash_Root_Element"
|
let rootElementName = "SWXMLHash_Root_Element"
|
||||||
|
|
||||||
/// Parser options
|
/// Parser options
|
||||||
public class SWXMLHashOptions {
|
public class XMLHashOptions {
|
||||||
internal init() {}
|
internal init() {}
|
||||||
|
|
||||||
/// determines whether to parse the XML with lazy parsing or not
|
/// determines whether to parse the XML with lazy parsing or not
|
||||||
@ -50,13 +53,20 @@ public class SWXMLHashOptions {
|
|||||||
|
|
||||||
/// Encoding used for XML parsing. Default is set to UTF8
|
/// Encoding used for XML parsing. Default is set to UTF8
|
||||||
public var encoding = String.Encoding.utf8
|
public var encoding = String.Encoding.utf8
|
||||||
|
|
||||||
|
/// Any contextual information set by the user for encoding
|
||||||
|
public var userInfo = [CodingUserInfoKey: Any]()
|
||||||
|
|
||||||
|
/// Detect XML parsing errors... defaults to false as this library will
|
||||||
|
/// attempt to handle HTML which isn't always XML-compatible
|
||||||
|
public var detectParsingErrors = false
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Simple XML parser
|
/// Simple XML parser
|
||||||
public class SWXMLHash {
|
public class XMLHash {
|
||||||
let options: SWXMLHashOptions
|
let options: XMLHashOptions
|
||||||
|
|
||||||
private init(_ options: SWXMLHashOptions = SWXMLHashOptions()) {
|
private init(_ options: XMLHashOptions = XMLHashOptions()) {
|
||||||
self.options = options
|
self.options = options
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,14 +74,14 @@ public class SWXMLHash {
|
|||||||
Method to configure how parsing works.
|
Method to configure how parsing works.
|
||||||
|
|
||||||
- parameters:
|
- parameters:
|
||||||
- configAction: a block that passes in an `SWXMLHashOptions` object with
|
- configAction: a block that passes in an `XMLHashOptions` object with
|
||||||
options to be set
|
options to be set
|
||||||
- returns: an `SWXMLHash` instance
|
- returns: an `XMLHash` instance
|
||||||
*/
|
*/
|
||||||
class public func config(_ configAction: (SWXMLHashOptions) -> Void) -> SWXMLHash {
|
class public func config(_ configAction: (XMLHashOptions) -> Void) -> XMLHash {
|
||||||
let opts = SWXMLHashOptions()
|
let opts = XMLHashOptions()
|
||||||
configAction(opts)
|
configAction(opts)
|
||||||
return SWXMLHash(opts)
|
return XMLHash(opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -110,7 +120,7 @@ public class SWXMLHash {
|
|||||||
- returns: An XMLIndexer instance that is used to look up elements in the XML
|
- returns: An XMLIndexer instance that is used to look up elements in the XML
|
||||||
*/
|
*/
|
||||||
class public func parse(_ xml: String) -> XMLIndexer {
|
class public func parse(_ xml: String) -> XMLIndexer {
|
||||||
return SWXMLHash().parse(xml)
|
XMLHash().parse(xml)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -120,7 +130,7 @@ public class SWXMLHash {
|
|||||||
- returns: An XMLIndexer instance that is used to look up elements in the XML
|
- returns: An XMLIndexer instance that is used to look up elements in the XML
|
||||||
*/
|
*/
|
||||||
class public func parse(_ data: Data) -> XMLIndexer {
|
class public func parse(_ data: Data) -> XMLIndexer {
|
||||||
return SWXMLHash().parse(data)
|
XMLHash().parse(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -130,7 +140,7 @@ public class SWXMLHash {
|
|||||||
- returns: An XMLIndexer instance that is used to look up elements in the XML
|
- returns: An XMLIndexer instance that is used to look up elements in the XML
|
||||||
*/
|
*/
|
||||||
class public func lazy(_ xml: String) -> XMLIndexer {
|
class public func lazy(_ xml: String) -> XMLIndexer {
|
||||||
return config { conf in conf.shouldProcessLazily = true }.parse(xml)
|
config { conf in conf.shouldProcessLazily = true }.parse(xml)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -140,128 +150,137 @@ public class SWXMLHash {
|
|||||||
- returns: An XMLIndexer instance that is used to look up elements in the XML
|
- returns: An XMLIndexer instance that is used to look up elements in the XML
|
||||||
*/
|
*/
|
||||||
class public func lazy(_ data: Data) -> XMLIndexer {
|
class public func lazy(_ data: Data) -> XMLIndexer {
|
||||||
return config { conf in conf.shouldProcessLazily = true }.parse(data)
|
config { conf in conf.shouldProcessLazily = true }.parse(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Stack<T> {
|
struct Stack<T> {
|
||||||
var items = [T]()
|
var items = [T]()
|
||||||
|
|
||||||
mutating func push(_ item: T) {
|
mutating func push(_ item: T) {
|
||||||
items.append(item)
|
items.append(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
mutating func pop() -> T {
|
mutating func pop() -> T {
|
||||||
return items.removeLast()
|
items.removeLast()
|
||||||
}
|
}
|
||||||
|
|
||||||
mutating func drop() {
|
mutating func drop() {
|
||||||
_ = pop()
|
_ = pop()
|
||||||
}
|
}
|
||||||
|
|
||||||
mutating func removeAll() {
|
mutating func removeAll() {
|
||||||
items.removeAll(keepingCapacity: false)
|
items.removeAll(keepingCapacity: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func top() -> T {
|
func top() -> T {
|
||||||
return items[items.count - 1]
|
items[items.count - 1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol SimpleXmlParser {
|
protocol SimpleXmlParser {
|
||||||
init(_ options: SWXMLHashOptions)
|
init(_ options: XMLHashOptions)
|
||||||
func parse(_ data: Data) -> XMLIndexer
|
func parse(_ data: Data) -> XMLIndexer
|
||||||
}
|
}
|
||||||
|
|
||||||
#if os(Linux)
|
#if os(Linux)
|
||||||
|
|
||||||
extension XMLParserDelegate {
|
extension XMLParserDelegate {
|
||||||
|
func parserDidStartDocument(_ parser: XMLParser) { }
|
||||||
|
func parserDidEndDocument(_ parser: XMLParser) { }
|
||||||
|
|
||||||
func parserDidStartDocument(_ parser: Foundation.XMLParser) { }
|
func parser(_ parser: XMLParser,
|
||||||
func parserDidEndDocument(_ parser: Foundation.XMLParser) { }
|
|
||||||
|
|
||||||
func parser(_ parser: Foundation.XMLParser,
|
|
||||||
foundNotationDeclarationWithName name: String,
|
foundNotationDeclarationWithName name: String,
|
||||||
publicID: String?,
|
publicID: String?,
|
||||||
systemID: String?) { }
|
systemID: String?) { }
|
||||||
|
|
||||||
func parser(_ parser: Foundation.XMLParser,
|
func parser(_ parser: XMLParser,
|
||||||
foundUnparsedEntityDeclarationWithName name: String,
|
foundUnparsedEntityDeclarationWithName name: String,
|
||||||
publicID: String?,
|
publicID: String?,
|
||||||
systemID: String?,
|
systemID: String?,
|
||||||
notationName: String?) { }
|
notationName: String?) { }
|
||||||
|
|
||||||
func parser(_ parser: Foundation.XMLParser,
|
func parser(_ parser: XMLParser,
|
||||||
foundAttributeDeclarationWithName attributeName: String,
|
foundAttributeDeclarationWithName attributeName: String,
|
||||||
forElement elementName: String,
|
forElement elementName: String,
|
||||||
type: String?,
|
type: String?,
|
||||||
defaultValue: String?) { }
|
defaultValue: String?) { }
|
||||||
|
|
||||||
func parser(_ parser: Foundation.XMLParser,
|
func parser(_ parser: XMLParser,
|
||||||
foundElementDeclarationWithName elementName: String,
|
foundElementDeclarationWithName elementName: String,
|
||||||
model: String) { }
|
model: String) { }
|
||||||
|
|
||||||
func parser(_ parser: Foundation.XMLParser,
|
func parser(_ parser: XMLParser,
|
||||||
foundInternalEntityDeclarationWithName name: String,
|
foundInternalEntityDeclarationWithName name: String,
|
||||||
value: String?) { }
|
value: String?) { }
|
||||||
|
|
||||||
func parser(_ parser: Foundation.XMLParser,
|
func parser(_ parser: XMLParser,
|
||||||
foundExternalEntityDeclarationWithName name: String,
|
foundExternalEntityDeclarationWithName name: String,
|
||||||
publicID: String?,
|
publicID: String?,
|
||||||
systemID: String?) { }
|
systemID: String?) { }
|
||||||
|
|
||||||
func parser(_ parser: Foundation.XMLParser,
|
func parser(_ parser: XMLParser,
|
||||||
didStartElement elementName: String,
|
didStartElement elementName: String,
|
||||||
namespaceURI: String?,
|
namespaceURI: String?,
|
||||||
qualifiedName qName: String?,
|
qualifiedName qName: String?,
|
||||||
attributes attributeDict: [String: String]) { }
|
attributes attributeDict: [String: String]) { }
|
||||||
|
|
||||||
func parser(_ parser: Foundation.XMLParser,
|
func parser(_ parser: XMLParser,
|
||||||
didEndElement elementName: String,
|
didEndElement elementName: String,
|
||||||
namespaceURI: String?,
|
namespaceURI: String?,
|
||||||
qualifiedName qName: String?) { }
|
qualifiedName qName: String?) { }
|
||||||
|
|
||||||
func parser(_ parser: Foundation.XMLParser,
|
func parser(_ parser: XMLParser,
|
||||||
didStartMappingPrefix prefix: String,
|
didStartMappingPrefix prefix: String,
|
||||||
toURI namespaceURI: String) { }
|
toURI namespaceURI: String) { }
|
||||||
|
|
||||||
func parser(_ parser: Foundation.XMLParser, didEndMappingPrefix prefix: String) { }
|
func parser(_ parser: XMLParser,
|
||||||
|
didEndMappingPrefix prefix: String) { }
|
||||||
|
|
||||||
func parser(_ parser: Foundation.XMLParser, foundCharacters string: String) { }
|
func parser(_ parser: XMLParser,
|
||||||
|
foundCharacters string: String) { }
|
||||||
|
|
||||||
func parser(_ parser: Foundation.XMLParser,
|
func parser(_ parser: XMLParser,
|
||||||
foundIgnorableWhitespace whitespaceString: String) { }
|
foundIgnorableWhitespace whitespaceString: String) { }
|
||||||
|
|
||||||
func parser(_ parser: Foundation.XMLParser,
|
func parser(_ parser: XMLParser,
|
||||||
foundProcessingInstructionWithTarget target: String,
|
foundProcessingInstructionWithTarget target: String,
|
||||||
data: String?) { }
|
data: String?) { }
|
||||||
|
|
||||||
func parser(_ parser: Foundation.XMLParser, foundComment comment: String) { }
|
func parser(_ parser: XMLParser,
|
||||||
|
foundComment comment: String) { }
|
||||||
|
|
||||||
func parser(_ parser: Foundation.XMLParser, foundCDATA CDATABlock: Data) { }
|
func parser(_ parser: XMLParser,
|
||||||
|
foundCDATA CDATABlock: Data) { }
|
||||||
|
|
||||||
func parser(_ parser: Foundation.XMLParser,
|
func parser(_ parser: XMLParser,
|
||||||
resolveExternalEntityName name: String,
|
resolveExternalEntityName name: String,
|
||||||
systemID: String?) -> Data? { return nil }
|
systemID: String?) -> Data? { nil }
|
||||||
|
|
||||||
func parser(_ parser: Foundation.XMLParser, parseErrorOccurred parseError: NSError) { }
|
func parser(_ parser: XMLParser,
|
||||||
|
parseErrorOccurred parseError: Error) { }
|
||||||
|
|
||||||
func parser(_ parser: Foundation.XMLParser,
|
func parser(_ parser: XMLParser,
|
||||||
validationErrorOccurred validationError: NSError) { }
|
validationErrorOccurred validationError: Error) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// The implementation of XMLParserDelegate and where the lazy parsing actually happens.
|
/// The implementation of XMLParserDelegate and where the lazy parsing actually happens.
|
||||||
class LazyXMLParser: NSObject, SimpleXmlParser, XMLParserDelegate {
|
class LazyXMLParser: NSObject, SimpleXmlParser, XMLParserDelegate {
|
||||||
required init(_ options: SWXMLHashOptions) {
|
required init(_ options: XMLHashOptions) {
|
||||||
|
root = XMLElement(name: rootElementName, options: options)
|
||||||
self.options = options
|
self.options = options
|
||||||
self.root.caseInsensitive = options.caseInsensitive
|
|
||||||
super.init()
|
super.init()
|
||||||
}
|
}
|
||||||
|
|
||||||
var root = XMLElement(name: rootElementName, caseInsensitive: false)
|
var root: XMLElement
|
||||||
var parentStack = Stack<XMLElement>()
|
var parentStack = Stack<XMLElement>()
|
||||||
var elementStack = Stack<String>()
|
var elementStack = Stack<String>()
|
||||||
|
|
||||||
var data: Data?
|
var data: Data?
|
||||||
var ops: [IndexOp] = []
|
var ops: [IndexOp] = []
|
||||||
let options: SWXMLHashOptions
|
let options: XMLHashOptions
|
||||||
|
|
||||||
func parse(_ data: Data) -> XMLIndexer {
|
func parse(_ data: Data) -> XMLIndexer {
|
||||||
self.data = data
|
self.data = data
|
||||||
@ -269,25 +288,23 @@ class LazyXMLParser: NSObject, SimpleXmlParser, XMLParserDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func startParsing(_ ops: [IndexOp]) {
|
func startParsing(_ ops: [IndexOp]) {
|
||||||
// clear any prior runs of parse... expected that this won't be necessary,
|
// reset state for a new lazy parsing run
|
||||||
// but you never know
|
root = XMLElement(name: rootElementName, options: root.options)
|
||||||
parentStack.removeAll()
|
parentStack.removeAll()
|
||||||
root = XMLElement(name: rootElementName, caseInsensitive: options.caseInsensitive)
|
|
||||||
parentStack.push(root)
|
parentStack.push(root)
|
||||||
|
|
||||||
self.ops = ops
|
self.ops = ops
|
||||||
let parser = Foundation.XMLParser(data: data!)
|
let parser = XMLParser(data: data!)
|
||||||
parser.shouldProcessNamespaces = options.shouldProcessNamespaces
|
parser.shouldProcessNamespaces = options.shouldProcessNamespaces
|
||||||
parser.delegate = self
|
parser.delegate = self
|
||||||
_ = parser.parse()
|
_ = parser.parse()
|
||||||
}
|
}
|
||||||
|
|
||||||
func parser(_ parser: Foundation.XMLParser,
|
func parser(_ parser: XMLParser,
|
||||||
didStartElement elementName: String,
|
didStartElement elementName: String,
|
||||||
namespaceURI: String?,
|
namespaceURI: String?,
|
||||||
qualifiedName qName: String?,
|
qualifiedName qName: String?,
|
||||||
attributes attributeDict: [String: String]) {
|
attributes attributeDict: [String: String]) {
|
||||||
|
|
||||||
elementStack.push(elementName)
|
elementStack.push(elementName)
|
||||||
|
|
||||||
if !onMatch() {
|
if !onMatch() {
|
||||||
@ -300,7 +317,7 @@ class LazyXMLParser: NSObject, SimpleXmlParser, XMLParserDelegate {
|
|||||||
parentStack.push(currentNode)
|
parentStack.push(currentNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parser(_ parser: Foundation.XMLParser, foundCharacters string: String) {
|
func parser(_ parser: XMLParser, foundCharacters string: String) {
|
||||||
if !onMatch() {
|
if !onMatch() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -310,11 +327,22 @@ class LazyXMLParser: NSObject, SimpleXmlParser, XMLParserDelegate {
|
|||||||
current.addText(string)
|
current.addText(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parser(_ parser: Foundation.XMLParser,
|
func parser(_ parser: XMLParser, foundCDATA CDATABlock: Data) {
|
||||||
|
if !onMatch() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if let cdataText = String(data: CDATABlock, encoding: String.Encoding.utf8) {
|
||||||
|
let current = parentStack.top()
|
||||||
|
|
||||||
|
current.addText(cdataText)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func parser(_ parser: XMLParser,
|
||||||
didEndElement elementName: String,
|
didEndElement elementName: String,
|
||||||
namespaceURI: String?,
|
namespaceURI: String?,
|
||||||
qualifiedName qName: String?) {
|
qualifiedName qName: String?) {
|
||||||
|
|
||||||
let match = onMatch()
|
let match = onMatch()
|
||||||
|
|
||||||
elementStack.drop()
|
elementStack.drop()
|
||||||
@ -337,15 +365,16 @@ class LazyXMLParser: NSObject, SimpleXmlParser, XMLParserDelegate {
|
|||||||
|
|
||||||
/// The implementation of XMLParserDelegate and where the parsing actually happens.
|
/// The implementation of XMLParserDelegate and where the parsing actually happens.
|
||||||
class FullXMLParser: NSObject, SimpleXmlParser, XMLParserDelegate {
|
class FullXMLParser: NSObject, SimpleXmlParser, XMLParserDelegate {
|
||||||
required init(_ options: SWXMLHashOptions) {
|
required init(_ options: XMLHashOptions) {
|
||||||
|
root = XMLElement(name: rootElementName, options: options)
|
||||||
self.options = options
|
self.options = options
|
||||||
self.root.caseInsensitive = options.caseInsensitive
|
|
||||||
super.init()
|
super.init()
|
||||||
}
|
}
|
||||||
|
|
||||||
var root = XMLElement(name: rootElementName, caseInsensitive: false)
|
let root: XMLElement
|
||||||
var parentStack = Stack<XMLElement>()
|
var parentStack = Stack<XMLElement>()
|
||||||
let options: SWXMLHashOptions
|
let options: XMLHashOptions
|
||||||
|
var parsingError: ParsingError?
|
||||||
|
|
||||||
func parse(_ data: Data) -> XMLIndexer {
|
func parse(_ data: Data) -> XMLIndexer {
|
||||||
// clear any prior runs of parse... expected that this won't be necessary,
|
// clear any prior runs of parse... expected that this won't be necessary,
|
||||||
@ -354,20 +383,23 @@ class FullXMLParser: NSObject, SimpleXmlParser, XMLParserDelegate {
|
|||||||
|
|
||||||
parentStack.push(root)
|
parentStack.push(root)
|
||||||
|
|
||||||
let parser = Foundation.XMLParser(data: data)
|
let parser = XMLParser(data: data)
|
||||||
parser.shouldProcessNamespaces = options.shouldProcessNamespaces
|
parser.shouldProcessNamespaces = options.shouldProcessNamespaces
|
||||||
parser.delegate = self
|
parser.delegate = self
|
||||||
_ = parser.parse()
|
_ = parser.parse()
|
||||||
|
|
||||||
|
if options.detectParsingErrors, let err = parsingError {
|
||||||
|
return XMLIndexer.parsingError(err)
|
||||||
|
} else {
|
||||||
return XMLIndexer(root)
|
return XMLIndexer(root)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func parser(_ parser: Foundation.XMLParser,
|
func parser(_ parser: XMLParser,
|
||||||
didStartElement elementName: String,
|
didStartElement elementName: String,
|
||||||
namespaceURI: String?,
|
namespaceURI: String?,
|
||||||
qualifiedName qName: String?,
|
qualifiedName qName: String?,
|
||||||
attributes attributeDict: [String: String]) {
|
attributes attributeDict: [String: String]) {
|
||||||
|
|
||||||
let currentNode = parentStack
|
let currentNode = parentStack
|
||||||
.top()
|
.top()
|
||||||
.addElement(elementName, withAttributes: attributeDict, caseInsensitive: self.options.caseInsensitive)
|
.addElement(elementName, withAttributes: attributeDict, caseInsensitive: self.options.caseInsensitive)
|
||||||
@ -375,19 +407,39 @@ class FullXMLParser: NSObject, SimpleXmlParser, XMLParserDelegate {
|
|||||||
parentStack.push(currentNode)
|
parentStack.push(currentNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parser(_ parser: Foundation.XMLParser, foundCharacters string: String) {
|
func parser(_ parser: XMLParser, foundCharacters string: String) {
|
||||||
let current = parentStack.top()
|
let current = parentStack.top()
|
||||||
|
|
||||||
current.addText(string)
|
current.addText(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parser(_ parser: Foundation.XMLParser,
|
func parser(_ parser: XMLParser,
|
||||||
didEndElement elementName: String,
|
didEndElement elementName: String,
|
||||||
namespaceURI: String?,
|
namespaceURI: String?,
|
||||||
qualifiedName qName: String?) {
|
qualifiedName qName: String?) {
|
||||||
|
|
||||||
parentStack.drop()
|
parentStack.drop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parser(_ parser: XMLParser, foundCDATA CDATABlock: Data) {
|
||||||
|
if let cdataText = String(data: CDATABlock, encoding: String.Encoding.utf8) {
|
||||||
|
let current = parentStack.top()
|
||||||
|
|
||||||
|
current.addText(cdataText)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func parser(_ parser: XMLParser, parseErrorOccurred parseError: Error) {
|
||||||
|
#if os(Linux) && !swift(>=4.1.50)
|
||||||
|
if let err = parseError as? NSError {
|
||||||
|
parsingError = ParsingError(line: err.userInfo["NSXMLParserErrorLineNumber"] as? Int ?? 0,
|
||||||
|
column: err.userInfo["NSXMLParserErrorColumn"] as? Int ?? 0)
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
let err = parseError as NSError
|
||||||
|
parsingError = ParsingError(line: err.userInfo["NSXMLParserErrorLineNumber"] as? Int ?? 0,
|
||||||
|
column: err.userInfo["NSXMLParserErrorColumn"] as? Int ?? 0)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents an indexed operation against a lazily parsed `XMLIndexer`
|
/// Represents an indexed operation against a lazily parsed `XMLIndexer`
|
||||||
@ -424,10 +476,10 @@ public class IndexOps {
|
|||||||
parser.startParsing(ops)
|
parser.startParsing(ops)
|
||||||
let indexer = XMLIndexer(parser.root)
|
let indexer = XMLIndexer(parser.root)
|
||||||
var childIndex = indexer
|
var childIndex = indexer
|
||||||
for op in ops {
|
for oper in ops {
|
||||||
childIndex = childIndex[op.key]
|
childIndex = childIndex[oper.key]
|
||||||
if op.index >= 0 {
|
if oper.index >= 0 {
|
||||||
childIndex = childIndex[op.index]
|
childIndex = childIndex[oper.index]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ops.removeAll(keepingCapacity: false)
|
ops.removeAll(keepingCapacity: false)
|
||||||
@ -435,14 +487,19 @@ public class IndexOps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func stringify() -> String {
|
func stringify() -> String {
|
||||||
var s = ""
|
var ret = ""
|
||||||
for op in ops {
|
for oper in ops {
|
||||||
s += "[" + op.toString() + "]"
|
ret += "[" + oper.toString() + "]"
|
||||||
}
|
}
|
||||||
return s
|
return ret
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct ParsingError: Error {
|
||||||
|
public let line: Int
|
||||||
|
public let column: Int
|
||||||
|
}
|
||||||
|
|
||||||
/// Error type that is thrown when an indexing or parsing operation fails.
|
/// Error type that is thrown when an indexing or parsing operation fails.
|
||||||
public enum IndexingError: Error {
|
public enum IndexingError: Error {
|
||||||
case attribute(attr: String)
|
case attribute(attr: String)
|
||||||
@ -459,22 +516,27 @@ public enum IndexingError: Error {
|
|||||||
public static func Attribute(attr: String) -> IndexingError {
|
public static func Attribute(attr: String) -> IndexingError {
|
||||||
fatalError("unavailable")
|
fatalError("unavailable")
|
||||||
}
|
}
|
||||||
|
|
||||||
@available(*, unavailable, renamed: "attributeValue(attr:value:)")
|
@available(*, unavailable, renamed: "attributeValue(attr:value:)")
|
||||||
public static func AttributeValue(attr: String, value: String) -> IndexingError {
|
public static func AttributeValue(attr: String, value: String) -> IndexingError {
|
||||||
fatalError("unavailable")
|
fatalError("unavailable")
|
||||||
}
|
}
|
||||||
|
|
||||||
@available(*, unavailable, renamed: "key(key:)")
|
@available(*, unavailable, renamed: "key(key:)")
|
||||||
public static func Key(key: String) -> IndexingError {
|
public static func Key(key: String) -> IndexingError {
|
||||||
fatalError("unavailable")
|
fatalError("unavailable")
|
||||||
}
|
}
|
||||||
|
|
||||||
@available(*, unavailable, renamed: "index(idx:)")
|
@available(*, unavailable, renamed: "index(idx:)")
|
||||||
public static func Index(idx: Int) -> IndexingError {
|
public static func Index(idx: Int) -> IndexingError {
|
||||||
fatalError("unavailable")
|
fatalError("unavailable")
|
||||||
}
|
}
|
||||||
|
|
||||||
@available(*, unavailable, renamed: "initialize(instance:)")
|
@available(*, unavailable, renamed: "initialize(instance:)")
|
||||||
public static func Init(instance: AnyObject) -> IndexingError {
|
public static func Init(instance: AnyObject) -> IndexingError {
|
||||||
fatalError("unavailable")
|
fatalError("unavailable")
|
||||||
}
|
}
|
||||||
|
|
||||||
@available(*, unavailable, renamed: "error")
|
@available(*, unavailable, renamed: "error")
|
||||||
public static var Error: IndexingError {
|
public static var Error: IndexingError {
|
||||||
fatalError("unavailable")
|
fatalError("unavailable")
|
||||||
@ -482,12 +544,13 @@ public enum IndexingError: Error {
|
|||||||
// swiftlint:enable identifier_name
|
// swiftlint:enable identifier_name
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returned from SWXMLHash, allows easy element lookup into XML data.
|
/// Returned from XMLHash, allows easy element lookup into XML data.
|
||||||
public enum XMLIndexer {
|
public enum XMLIndexer {
|
||||||
case element(XMLElement)
|
case element(XMLElement)
|
||||||
case list([XMLElement])
|
case list([XMLElement])
|
||||||
case stream(IndexOps)
|
case stream(IndexOps)
|
||||||
case xmlError(IndexingError)
|
case xmlError(IndexingError)
|
||||||
|
case parsingError(ParsingError)
|
||||||
|
|
||||||
// swiftlint:disable identifier_name
|
// swiftlint:disable identifier_name
|
||||||
// unavailable
|
// unavailable
|
||||||
@ -528,18 +591,18 @@ public enum XMLIndexer {
|
|||||||
|
|
||||||
/// All elements at the currently indexed level
|
/// All elements at the currently indexed level
|
||||||
public var all: [XMLIndexer] {
|
public var all: [XMLIndexer] {
|
||||||
|
allElements.map { XMLIndexer($0) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private var allElements: [XMLElement] {
|
||||||
switch self {
|
switch self {
|
||||||
case .list(let list):
|
case .list(let list):
|
||||||
var xmlList = [XMLIndexer]()
|
return list
|
||||||
for elem in list {
|
|
||||||
xmlList.append(XMLIndexer(elem))
|
|
||||||
}
|
|
||||||
return xmlList
|
|
||||||
case .element(let elem):
|
case .element(let elem):
|
||||||
return [XMLIndexer(elem)]
|
return [elem]
|
||||||
case .stream(let ops):
|
case .stream(let ops):
|
||||||
let list = ops.findElements()
|
let list = ops.findElements()
|
||||||
return list.all
|
return list.allElements
|
||||||
default:
|
default:
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
@ -547,15 +610,56 @@ public enum XMLIndexer {
|
|||||||
|
|
||||||
/// All child elements from the currently indexed level
|
/// All child elements from the currently indexed level
|
||||||
public var children: [XMLIndexer] {
|
public var children: [XMLIndexer] {
|
||||||
var list = [XMLIndexer]()
|
childElements.map { XMLIndexer($0) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private var childElements: [XMLElement] {
|
||||||
|
var list = [XMLElement]()
|
||||||
for elem in all.compactMap({ $0.element }) {
|
for elem in all.compactMap({ $0.element }) {
|
||||||
for elem in elem.xmlChildren {
|
for elem in elem.xmlChildren {
|
||||||
list.append(XMLIndexer(elem))
|
list.append(elem)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@available(*, unavailable, renamed: "filterChildren(_:)")
|
||||||
|
public func filter(_ included: (_ elem: XMLElement, _ index: Int) -> Bool) -> XMLIndexer {
|
||||||
|
filterChildren(included)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func filterChildren(_ included: (_ elem: XMLElement, _ index: Int) -> Bool) -> XMLIndexer {
|
||||||
|
let children = handleFilteredResults(list: childElements, included: included)
|
||||||
|
if let current = self.element {
|
||||||
|
let filteredElem = XMLElement(name: current.name, index: current.index, options: current.options)
|
||||||
|
filteredElem.children = children.allElements
|
||||||
|
return .element(filteredElem)
|
||||||
|
}
|
||||||
|
return .xmlError(IndexingError.error)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func filterAll(_ included: (_ elem: XMLElement, _ index: Int) -> Bool) -> XMLIndexer {
|
||||||
|
handleFilteredResults(list: allElements, included: included)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func handleFilteredResults(list: [XMLElement],
|
||||||
|
included: (_ elem: XMLElement, _ index: Int) -> Bool) -> XMLIndexer {
|
||||||
|
let results = zip(list.indices, list).filter { included($1, $0) }.map { $1 }
|
||||||
|
if results.count == 1 {
|
||||||
|
return .element(results.first!)
|
||||||
|
}
|
||||||
|
return .list(results)
|
||||||
|
}
|
||||||
|
|
||||||
|
public var userInfo: [CodingUserInfoKey: Any] {
|
||||||
|
switch self {
|
||||||
|
case .element(let elem):
|
||||||
|
return elem.userInfo
|
||||||
|
default:
|
||||||
|
return [:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Allows for element lookup by matching attribute values.
|
Allows for element lookup by matching attribute values.
|
||||||
|
|
||||||
@ -627,8 +731,8 @@ public enum XMLIndexer {
|
|||||||
public func byKey(_ key: String) throws -> XMLIndexer {
|
public func byKey(_ key: String) throws -> XMLIndexer {
|
||||||
switch self {
|
switch self {
|
||||||
case .stream(let opStream):
|
case .stream(let opStream):
|
||||||
let op = IndexOp(key)
|
let oper = IndexOp(key)
|
||||||
opStream.ops.append(op)
|
opStream.ops.append(oper)
|
||||||
return .stream(opStream)
|
return .stream(opStream)
|
||||||
case .element(let elem):
|
case .element(let elem):
|
||||||
let match = elem.xmlChildren.filter({
|
let match = elem.xmlChildren.filter({
|
||||||
@ -641,7 +745,7 @@ public enum XMLIndexer {
|
|||||||
return .list(match)
|
return .list(match)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fallthrough
|
throw IndexingError.key(key: key)
|
||||||
default:
|
default:
|
||||||
throw IndexingError.key(key: key)
|
throw IndexingError.key(key: key)
|
||||||
}
|
}
|
||||||
@ -676,7 +780,7 @@ public enum XMLIndexer {
|
|||||||
opStream.ops[opStream.ops.count - 1].index = index
|
opStream.ops[opStream.ops.count - 1].index = index
|
||||||
return .stream(opStream)
|
return .stream(opStream)
|
||||||
case .list(let list):
|
case .list(let list):
|
||||||
if index <= list.count {
|
if index < list.count {
|
||||||
return .element(list[index])
|
return .element(list[index])
|
||||||
}
|
}
|
||||||
return .xmlError(IndexingError.index(idx: index))
|
return .xmlError(IndexingError.index(idx: index))
|
||||||
@ -684,7 +788,7 @@ public enum XMLIndexer {
|
|||||||
if index == 0 {
|
if index == 0 {
|
||||||
return .element(elem)
|
return .element(elem)
|
||||||
}
|
}
|
||||||
fallthrough
|
return .xmlError(IndexingError.index(idx: index))
|
||||||
default:
|
default:
|
||||||
return .xmlError(IndexingError.index(idx: index))
|
return .xmlError(IndexingError.index(idx: index))
|
||||||
}
|
}
|
||||||
@ -733,7 +837,7 @@ extension IndexingError: CustomStringConvertible {
|
|||||||
switch self {
|
switch self {
|
||||||
case .attribute(let attr):
|
case .attribute(let attr):
|
||||||
return "XML Attribute Error: Missing attribute [\"\(attr)\"]"
|
return "XML Attribute Error: Missing attribute [\"\(attr)\"]"
|
||||||
case .attributeValue(let attr, let value):
|
case let .attributeValue(attr, value):
|
||||||
return "XML Attribute Error: Missing attribute [\"\(attr)\"] with value [\"\(value)\"]"
|
return "XML Attribute Error: Missing attribute [\"\(attr)\"] with value [\"\(value)\"]"
|
||||||
case .key(let key):
|
case .key(let key):
|
||||||
return "XML Element Error: Incorrect key [\"\(key)\"]"
|
return "XML Element Error: Incorrect key [\"\(key)\"]"
|
||||||
@ -756,6 +860,7 @@ public protocol XMLContent: CustomStringConvertible { }
|
|||||||
public class TextElement: XMLContent {
|
public class TextElement: XMLContent {
|
||||||
/// The underlying text value
|
/// The underlying text value
|
||||||
public let text: String
|
public let text: String
|
||||||
|
|
||||||
init(text: String) {
|
init(text: String) {
|
||||||
self.text = text
|
self.text = text
|
||||||
}
|
}
|
||||||
@ -764,6 +869,7 @@ public class TextElement: XMLContent {
|
|||||||
public struct XMLAttribute {
|
public struct XMLAttribute {
|
||||||
public let name: String
|
public let name: String
|
||||||
public let text: String
|
public let text: String
|
||||||
|
|
||||||
init(name: String, text: String) {
|
init(name: String, text: String) {
|
||||||
self.name = name
|
self.name = name
|
||||||
self.text = text
|
self.text = text
|
||||||
@ -775,11 +881,19 @@ public class XMLElement: XMLContent {
|
|||||||
/// The name of the element
|
/// The name of the element
|
||||||
public let name: String
|
public let name: String
|
||||||
|
|
||||||
public var caseInsensitive: Bool
|
/// Whether the element is case insensitive or not
|
||||||
|
public var caseInsensitive: Bool {
|
||||||
|
options.caseInsensitive
|
||||||
|
}
|
||||||
|
|
||||||
|
var userInfo: [CodingUserInfoKey: Any] {
|
||||||
|
options.userInfo
|
||||||
|
}
|
||||||
|
|
||||||
/// All attributes
|
/// All attributes
|
||||||
public var allAttributes = [String: XMLAttribute]()
|
public var allAttributes = [String: XMLAttribute]()
|
||||||
|
|
||||||
|
/// Find an attribute by name
|
||||||
public func attribute(by name: String) -> XMLAttribute? {
|
public func attribute(by name: String) -> XMLAttribute? {
|
||||||
if caseInsensitive {
|
if caseInsensitive {
|
||||||
return allAttributes.first(where: { $0.key.compare(name, true) })?.value
|
return allAttributes.first(where: { $0.key.compare(name, true) })?.value
|
||||||
@ -789,7 +903,7 @@ public class XMLElement: XMLContent {
|
|||||||
|
|
||||||
/// The inner text of the element, if it exists
|
/// The inner text of the element, if it exists
|
||||||
public var text: String {
|
public var text: String {
|
||||||
return children.reduce("", {
|
children.reduce("", {
|
||||||
if let element = $1 as? TextElement {
|
if let element = $1 as? TextElement {
|
||||||
return $0 + element.text
|
return $0 + element.text
|
||||||
}
|
}
|
||||||
@ -800,7 +914,7 @@ public class XMLElement: XMLContent {
|
|||||||
|
|
||||||
/// The inner text of the element and its children
|
/// The inner text of the element and its children
|
||||||
public var recursiveText: String {
|
public var recursiveText: String {
|
||||||
return children.reduce("", {
|
children.reduce("", {
|
||||||
if let textElement = $1 as? TextElement {
|
if let textElement = $1 as? TextElement {
|
||||||
return $0 + textElement.text
|
return $0 + textElement.text
|
||||||
} else if let xmlElement = $1 as? XMLElement {
|
} else if let xmlElement = $1 as? XMLElement {
|
||||||
@ -811,13 +925,21 @@ public class XMLElement: XMLContent {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public var innerXML: String {
|
||||||
|
children.reduce("", {
|
||||||
|
$0.description + $1.description
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// All child elements (text or XML)
|
/// All child elements (text or XML)
|
||||||
public var children = [XMLContent]()
|
public var children = [XMLContent]()
|
||||||
|
|
||||||
var count: Int = 0
|
var count: Int = 0
|
||||||
var index: Int
|
var index: Int
|
||||||
|
let options: XMLHashOptions
|
||||||
|
|
||||||
var xmlChildren: [XMLElement] {
|
var xmlChildren: [XMLElement] {
|
||||||
return children.compactMap { $0 as? XMLElement }
|
children.compactMap { $0 as? XMLElement }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -826,11 +948,12 @@ public class XMLElement: XMLContent {
|
|||||||
- parameters:
|
- parameters:
|
||||||
- name: The name of the element to be initialized
|
- name: The name of the element to be initialized
|
||||||
- index: The index of the element to be initialized
|
- index: The index of the element to be initialized
|
||||||
|
- options: The XMLHash options
|
||||||
*/
|
*/
|
||||||
init(name: String, index: Int = 0, caseInsensitive: Bool) {
|
init(name: String, index: Int = 0, options: XMLHashOptions) {
|
||||||
self.name = name
|
self.name = name
|
||||||
self.caseInsensitive = caseInsensitive
|
|
||||||
self.index = index
|
self.index = index
|
||||||
|
self.options = options
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -843,7 +966,7 @@ public class XMLElement: XMLContent {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
func addElement(_ name: String, withAttributes attributes: [String: String], caseInsensitive: Bool) -> XMLElement {
|
func addElement(_ name: String, withAttributes attributes: [String: String], caseInsensitive: Bool) -> XMLElement {
|
||||||
let element = XMLElement(name: name, index: count, caseInsensitive: caseInsensitive)
|
let element = XMLElement(name: name, index: count, options: options)
|
||||||
count += 1
|
count += 1
|
||||||
|
|
||||||
children.append(element)
|
children.append(element)
|
||||||
@ -865,14 +988,14 @@ public class XMLElement: XMLContent {
|
|||||||
extension TextElement: CustomStringConvertible {
|
extension TextElement: CustomStringConvertible {
|
||||||
/// The text value for a `TextElement` instance.
|
/// The text value for a `TextElement` instance.
|
||||||
public var description: String {
|
public var description: String {
|
||||||
return text
|
text
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension XMLAttribute: CustomStringConvertible {
|
extension XMLAttribute: CustomStringConvertible {
|
||||||
/// The textual representation of an `XMLAttribute` instance.
|
/// The textual representation of an `XMLAttribute` instance.
|
||||||
public var description: String {
|
public var description: String {
|
||||||
return "\(name)=\"\(text)\""
|
"\(name)=\"\(text)\""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -888,7 +1011,7 @@ extension XMLElement: CustomStringConvertible {
|
|||||||
xmlReturn.append(child.description)
|
xmlReturn.append(child.description)
|
||||||
}
|
}
|
||||||
xmlReturn.append("</\(name)>")
|
xmlReturn.append("</\(name)>")
|
||||||
return xmlReturn.joined(separator: "")
|
return xmlReturn.joined()
|
||||||
}
|
}
|
||||||
|
|
||||||
return "<\(name)\(attributesString)>\(text)</\(name)>"
|
return "<\(name)\(attributesString)>\(text)</\(name)>"
|
||||||
@ -900,11 +1023,11 @@ extension XMLElement: CustomStringConvertible {
|
|||||||
// On macOS, `XMLElement` is defined in Foundation.
|
// On macOS, `XMLElement` is defined in Foundation.
|
||||||
// So, the code referencing `XMLElement` generates above error.
|
// So, the code referencing `XMLElement` generates above error.
|
||||||
// Following code allow to using `SWXMLhash.XMLElement` in client codes.
|
// Following code allow to using `SWXMLhash.XMLElement` in client codes.
|
||||||
extension SWXMLHash {
|
extension XMLHash {
|
||||||
public typealias XMLElement = SWXMLHashXMLElement
|
public typealias XMLElement = XMLHashXMLElement
|
||||||
}
|
}
|
||||||
|
|
||||||
public typealias SWXMLHashXMLElement = XMLElement
|
public typealias XMLHashXMLElement = XMLElement
|
||||||
|
|
||||||
fileprivate extension String {
|
fileprivate extension String {
|
||||||
func compare(_ str2: String?, _ insensitive: Bool) -> Bool {
|
func compare(_ str2: String?, _ insensitive: Bool) -> Bool {
|
||||||
@ -918,3 +1041,72 @@ fileprivate extension String {
|
|||||||
return str1 == str2
|
return str1 == str2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - XMLIndexer String RawRepresentables
|
||||||
|
|
||||||
|
/*: Provides XMLIndexer Serialization/Deserialization using String backed RawRepresentables
|
||||||
|
Added by [PeeJWeeJ](https://github.com/PeeJWeeJ) */
|
||||||
|
extension XMLIndexer {
|
||||||
|
/**
|
||||||
|
Allows for element lookup by matching attribute values
|
||||||
|
using a String backed RawRepresentables (E.g. `String` backed `enum` cases)
|
||||||
|
|
||||||
|
- Note:
|
||||||
|
Convenience for withAttribute(String, String)
|
||||||
|
|
||||||
|
- parameters:
|
||||||
|
- attr: should the name of the attribute to match on
|
||||||
|
- value: should be the value of the attribute to match on
|
||||||
|
- throws: an XMLIndexer.XMLError if an element with the specified attribute isn't found
|
||||||
|
- returns: instance of XMLIndexer
|
||||||
|
*/
|
||||||
|
public func withAttribute<A: RawRepresentable, V: RawRepresentable>(_ attr: A, _ value: V) throws -> XMLIndexer
|
||||||
|
where A.RawValue == String, V.RawValue == String {
|
||||||
|
try withAttribute(attr.rawValue, value.rawValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Find an XML element at the current level by element name
|
||||||
|
using a String backed RawRepresentable (E.g. `String` backed `enum` cases)
|
||||||
|
|
||||||
|
- Note:
|
||||||
|
Convenience for byKey(String)
|
||||||
|
|
||||||
|
- parameter key: The element name to index by
|
||||||
|
- returns: instance of XMLIndexer to match the element (or elements) found by key
|
||||||
|
- throws: Throws an XMLIndexingError.Key if no element was found
|
||||||
|
*/
|
||||||
|
public func byKey<K: RawRepresentable>(_ key: K) throws -> XMLIndexer where K.RawValue == String {
|
||||||
|
try byKey(key.rawValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Find an XML element at the current level by element name
|
||||||
|
using a String backed RawRepresentable (E.g. `String` backed `enum` cases)
|
||||||
|
|
||||||
|
- Note:
|
||||||
|
Convenience for self[String]
|
||||||
|
|
||||||
|
- parameter key: The element name to index by
|
||||||
|
- returns: instance of XMLIndexer to match the element (or elements) found by
|
||||||
|
*/
|
||||||
|
public subscript<K: RawRepresentable>(key: K) -> XMLIndexer where K.RawValue == String {
|
||||||
|
self[key.rawValue]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - XMLElement String RawRepresentables
|
||||||
|
|
||||||
|
/*: Provides XMLIndexer Serialization/Deserialization using String backed RawRepresentables
|
||||||
|
Added by [PeeJWeeJ](https://github.com/PeeJWeeJ) */
|
||||||
|
extension XMLElement {
|
||||||
|
/**
|
||||||
|
Find an attribute by name using a String backed RawRepresentable (E.g. `String` backed `enum` cases)
|
||||||
|
|
||||||
|
- Note:
|
||||||
|
Convenience for self[String]
|
||||||
|
*/
|
||||||
|
public func attribute<N: RawRepresentable>(by name: N) -> XMLAttribute? where N.RawValue == String {
|
||||||
|
attribute(by: name.rawValue)
|
||||||
|
}
|
||||||
|
}
|
259
Dependencies/SWXMLHash/SWXMLHash+TypeConversion.swift → Dependencies/SWXMLHash/XMLIndexer+XMLIndexerDeserializable.swift
vendored
Executable file → Normal file
259
Dependencies/SWXMLHash/SWXMLHash+TypeConversion.swift → Dependencies/SWXMLHash/XMLIndexer+XMLIndexerDeserializable.swift
vendored
Executable file → Normal file
@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// SWXMLHash+TypeConversion.swift
|
// XMLHash+TypeConversion.swift
|
||||||
// SWXMLHash
|
// SWXMLHash
|
||||||
//
|
//
|
||||||
// Copyright (c) 2016 Maciek Grzybowskio
|
// Copyright (c) 2016 Maciek Grzybowskio
|
||||||
@ -34,6 +34,8 @@ import Foundation
|
|||||||
public protocol XMLIndexerDeserializable {
|
public protocol XMLIndexerDeserializable {
|
||||||
/// Method for deserializing elements from XMLIndexer
|
/// Method for deserializing elements from XMLIndexer
|
||||||
static func deserialize(_ element: XMLIndexer) throws -> Self
|
static func deserialize(_ element: XMLIndexer) throws -> Self
|
||||||
|
/// Method for validating elements post deserialization
|
||||||
|
func validate() throws
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Provides XMLIndexer deserialization / type transformation support
|
/// Provides XMLIndexer deserialization / type transformation support
|
||||||
@ -50,6 +52,12 @@ public extension XMLIndexerDeserializable {
|
|||||||
throw XMLDeserializationError.implementationIsMissing(
|
throw XMLDeserializationError.implementationIsMissing(
|
||||||
method: "XMLIndexerDeserializable.deserialize(element: XMLIndexer)")
|
method: "XMLIndexerDeserializable.deserialize(element: XMLIndexer)")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
A default do nothing implementation of validation.
|
||||||
|
- throws: nothing
|
||||||
|
*/
|
||||||
|
func validate() throws {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - XMLElementDeserializable
|
// MARK: - XMLElementDeserializable
|
||||||
@ -58,6 +66,8 @@ public extension XMLIndexerDeserializable {
|
|||||||
public protocol XMLElementDeserializable {
|
public protocol XMLElementDeserializable {
|
||||||
/// Method for deserializing elements from XMLElement
|
/// Method for deserializing elements from XMLElement
|
||||||
static func deserialize(_ element: XMLElement) throws -> Self
|
static func deserialize(_ element: XMLElement) throws -> Self
|
||||||
|
/// Method for validating elements from XMLElement post deserialization
|
||||||
|
func validate() throws
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Provides XMLElement deserialization / type transformation support
|
/// Provides XMLElement deserialization / type transformation support
|
||||||
@ -74,13 +84,22 @@ public extension XMLElementDeserializable {
|
|||||||
throw XMLDeserializationError.implementationIsMissing(
|
throw XMLDeserializationError.implementationIsMissing(
|
||||||
method: "XMLElementDeserializable.deserialize(element: XMLElement)")
|
method: "XMLElementDeserializable.deserialize(element: XMLElement)")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
A default do nothing implementation of validation.
|
||||||
|
- throws: nothing
|
||||||
|
*/
|
||||||
|
func validate() throws {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - XMLAttributeDeserializable
|
// MARK: - XMLAttributeDeserializable
|
||||||
|
|
||||||
/// Provides XMLAttribute deserialization / type transformation support
|
/// Provides XMLAttribute deserialization / type transformation support
|
||||||
public protocol XMLAttributeDeserializable {
|
public protocol XMLAttributeDeserializable {
|
||||||
|
/// Method for deserializing elements from XMLAttribute
|
||||||
static func deserialize(_ attribute: XMLAttribute) throws -> Self
|
static func deserialize(_ attribute: XMLAttribute) throws -> Self
|
||||||
|
/// Method for validating elements from XMLAttribute post deserialization
|
||||||
|
func validate() throws
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Provides XMLAttribute deserialization / type transformation support
|
/// Provides XMLAttribute deserialization / type transformation support
|
||||||
@ -97,12 +116,16 @@ public extension XMLAttributeDeserializable {
|
|||||||
throw XMLDeserializationError.implementationIsMissing(
|
throw XMLDeserializationError.implementationIsMissing(
|
||||||
method: "XMLAttributeDeserializable(element: XMLAttribute)")
|
method: "XMLAttributeDeserializable(element: XMLAttribute)")
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
A default do nothing implementation of validation.
|
||||||
|
- throws: nothing
|
||||||
|
*/
|
||||||
|
func validate() throws {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - XMLIndexer Extensions
|
// MARK: - XMLIndexer Extensions
|
||||||
|
|
||||||
public extension XMLIndexer {
|
public extension XMLIndexer {
|
||||||
|
|
||||||
// MARK: - XMLAttributeDeserializable
|
// MARK: - XMLAttributeDeserializable
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -216,7 +239,9 @@ public extension XMLIndexer {
|
|||||||
func value<T: XMLElementDeserializable>() throws -> T {
|
func value<T: XMLElementDeserializable>() throws -> T {
|
||||||
switch self {
|
switch self {
|
||||||
case .element(let element):
|
case .element(let element):
|
||||||
return try T.deserialize(element)
|
let deserialized = try T.deserialize(element)
|
||||||
|
try deserialized.validate()
|
||||||
|
return deserialized
|
||||||
case .stream(let opStream):
|
case .stream(let opStream):
|
||||||
return try opStream.findElements().value()
|
return try opStream.findElements().value()
|
||||||
default:
|
default:
|
||||||
@ -233,7 +258,9 @@ public extension XMLIndexer {
|
|||||||
func value<T: XMLElementDeserializable>() throws -> T? {
|
func value<T: XMLElementDeserializable>() throws -> T? {
|
||||||
switch self {
|
switch self {
|
||||||
case .element(let element):
|
case .element(let element):
|
||||||
return try T.deserialize(element)
|
let deserialized = try T.deserialize(element)
|
||||||
|
try deserialized.validate()
|
||||||
|
return deserialized
|
||||||
case .stream(let opStream):
|
case .stream(let opStream):
|
||||||
return try opStream.findElements().value()
|
return try opStream.findElements().value()
|
||||||
default:
|
default:
|
||||||
@ -250,9 +277,17 @@ public extension XMLIndexer {
|
|||||||
func value<T: XMLElementDeserializable>() throws -> [T] {
|
func value<T: XMLElementDeserializable>() throws -> [T] {
|
||||||
switch self {
|
switch self {
|
||||||
case .list(let elements):
|
case .list(let elements):
|
||||||
return try elements.map { try T.deserialize($0) }
|
return try elements.map {
|
||||||
|
let deserialized = try T.deserialize($0)
|
||||||
|
try deserialized.validate()
|
||||||
|
return deserialized
|
||||||
|
}
|
||||||
case .element(let element):
|
case .element(let element):
|
||||||
return try [element].map { try T.deserialize($0) }
|
return try [element].map {
|
||||||
|
let deserialized = try T.deserialize($0)
|
||||||
|
try deserialized.validate()
|
||||||
|
return deserialized
|
||||||
|
}
|
||||||
case .stream(let opStream):
|
case .stream(let opStream):
|
||||||
return try opStream.findElements().value()
|
return try opStream.findElements().value()
|
||||||
default:
|
default:
|
||||||
@ -269,9 +304,17 @@ public extension XMLIndexer {
|
|||||||
func value<T: XMLElementDeserializable>() throws -> [T]? {
|
func value<T: XMLElementDeserializable>() throws -> [T]? {
|
||||||
switch self {
|
switch self {
|
||||||
case .list(let elements):
|
case .list(let elements):
|
||||||
return try elements.map { try T.deserialize($0) }
|
return try elements.map {
|
||||||
|
let deserialized = try T.deserialize($0)
|
||||||
|
try deserialized.validate()
|
||||||
|
return deserialized
|
||||||
|
}
|
||||||
case .element(let element):
|
case .element(let element):
|
||||||
return try [element].map { try T.deserialize($0) }
|
return try [element].map {
|
||||||
|
let deserialized = try T.deserialize($0)
|
||||||
|
try deserialized.validate()
|
||||||
|
return deserialized
|
||||||
|
}
|
||||||
case .stream(let opStream):
|
case .stream(let opStream):
|
||||||
return try opStream.findElements().value()
|
return try opStream.findElements().value()
|
||||||
default:
|
default:
|
||||||
@ -288,9 +331,17 @@ public extension XMLIndexer {
|
|||||||
func value<T: XMLElementDeserializable>() throws -> [T?] {
|
func value<T: XMLElementDeserializable>() throws -> [T?] {
|
||||||
switch self {
|
switch self {
|
||||||
case .list(let elements):
|
case .list(let elements):
|
||||||
return try elements.map { try T.deserialize($0) }
|
return try elements.map {
|
||||||
|
let deserialized = try T.deserialize($0)
|
||||||
|
try deserialized.validate()
|
||||||
|
return deserialized
|
||||||
|
}
|
||||||
case .element(let element):
|
case .element(let element):
|
||||||
return try [element].map { try T.deserialize($0) }
|
return try [element].map {
|
||||||
|
let deserialized = try T.deserialize($0)
|
||||||
|
try deserialized.validate()
|
||||||
|
return deserialized
|
||||||
|
}
|
||||||
case .stream(let opStream):
|
case .stream(let opStream):
|
||||||
return try opStream.findElements().value()
|
return try opStream.findElements().value()
|
||||||
default:
|
default:
|
||||||
@ -309,7 +360,9 @@ public extension XMLIndexer {
|
|||||||
func value<T: XMLIndexerDeserializable>() throws -> T {
|
func value<T: XMLIndexerDeserializable>() throws -> T {
|
||||||
switch self {
|
switch self {
|
||||||
case .element:
|
case .element:
|
||||||
return try T.deserialize(self)
|
let deserialized = try T.deserialize(self)
|
||||||
|
try deserialized.validate()
|
||||||
|
return deserialized
|
||||||
case .stream(let opStream):
|
case .stream(let opStream):
|
||||||
return try opStream.findElements().value()
|
return try opStream.findElements().value()
|
||||||
default:
|
default:
|
||||||
@ -326,7 +379,9 @@ public extension XMLIndexer {
|
|||||||
func value<T: XMLIndexerDeserializable>() throws -> T? {
|
func value<T: XMLIndexerDeserializable>() throws -> T? {
|
||||||
switch self {
|
switch self {
|
||||||
case .element:
|
case .element:
|
||||||
return try T.deserialize(self)
|
let deserialized = try T.deserialize(self)
|
||||||
|
try deserialized.validate()
|
||||||
|
return deserialized
|
||||||
case .stream(let opStream):
|
case .stream(let opStream):
|
||||||
return try opStream.findElements().value()
|
return try opStream.findElements().value()
|
||||||
default:
|
default:
|
||||||
@ -343,9 +398,17 @@ public extension XMLIndexer {
|
|||||||
func value<T>() throws -> [T] where T: XMLIndexerDeserializable {
|
func value<T>() throws -> [T] where T: XMLIndexerDeserializable {
|
||||||
switch self {
|
switch self {
|
||||||
case .list(let elements):
|
case .list(let elements):
|
||||||
return try elements.map { try T.deserialize( XMLIndexer($0) ) }
|
return try elements.map {
|
||||||
|
let deserialized = try T.deserialize( XMLIndexer($0) )
|
||||||
|
try deserialized.validate()
|
||||||
|
return deserialized
|
||||||
|
}
|
||||||
case .element(let element):
|
case .element(let element):
|
||||||
return try [element].map { try T.deserialize( XMLIndexer($0) ) }
|
return try [element].map {
|
||||||
|
let deserialized = try T.deserialize( XMLIndexer($0) )
|
||||||
|
try deserialized.validate()
|
||||||
|
return deserialized
|
||||||
|
}
|
||||||
case .stream(let opStream):
|
case .stream(let opStream):
|
||||||
return try opStream.findElements().value()
|
return try opStream.findElements().value()
|
||||||
default:
|
default:
|
||||||
@ -362,9 +425,17 @@ public extension XMLIndexer {
|
|||||||
func value<T: XMLIndexerDeserializable>() throws -> [T]? {
|
func value<T: XMLIndexerDeserializable>() throws -> [T]? {
|
||||||
switch self {
|
switch self {
|
||||||
case .list(let elements):
|
case .list(let elements):
|
||||||
return try elements.map { try T.deserialize( XMLIndexer($0) ) }
|
return try elements.map {
|
||||||
|
let deserialized = try T.deserialize(XMLIndexer($0))
|
||||||
|
try deserialized.validate()
|
||||||
|
return deserialized
|
||||||
|
}
|
||||||
case .element(let element):
|
case .element(let element):
|
||||||
return try [element].map { try T.deserialize( XMLIndexer($0) ) }
|
return try [element].map {
|
||||||
|
let deserialized = try T.deserialize(XMLIndexer($0))
|
||||||
|
try deserialized.validate()
|
||||||
|
return deserialized
|
||||||
|
}
|
||||||
case .stream(let opStream):
|
case .stream(let opStream):
|
||||||
return try opStream.findElements().value()
|
return try opStream.findElements().value()
|
||||||
default:
|
default:
|
||||||
@ -381,9 +452,17 @@ public extension XMLIndexer {
|
|||||||
func value<T: XMLIndexerDeserializable>() throws -> [T?] {
|
func value<T: XMLIndexerDeserializable>() throws -> [T?] {
|
||||||
switch self {
|
switch self {
|
||||||
case .list(let elements):
|
case .list(let elements):
|
||||||
return try elements.map { try T.deserialize( XMLIndexer($0) ) }
|
return try elements.map {
|
||||||
|
let deserialized = try T.deserialize(XMLIndexer($0))
|
||||||
|
try deserialized.validate()
|
||||||
|
return deserialized
|
||||||
|
}
|
||||||
case .element(let element):
|
case .element(let element):
|
||||||
return try [element].map { try T.deserialize( XMLIndexer($0) ) }
|
return try [element].map {
|
||||||
|
let deserialized = try T.deserialize(XMLIndexer($0))
|
||||||
|
try deserialized.validate()
|
||||||
|
return deserialized
|
||||||
|
}
|
||||||
case .stream(let opStream):
|
case .stream(let opStream):
|
||||||
return try opStream.findElements().value()
|
return try opStream.findElements().value()
|
||||||
default:
|
default:
|
||||||
@ -392,10 +471,89 @@ public extension XMLIndexer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - XMLAttributeDeserializable String RawRepresentable
|
||||||
|
|
||||||
|
/*: Provides XMLIndexer XMLAttributeDeserializable deserialization from String backed RawRepresentables
|
||||||
|
Added by [PeeJWeeJ](https://github.com/PeeJWeeJ) */
|
||||||
|
public extension XMLIndexer {
|
||||||
|
/**
|
||||||
|
Attempts to deserialize the value of the specified attribute of the current XMLIndexer
|
||||||
|
element to `T` using a String backed RawRepresentable (E.g. `String` backed `enum` cases)
|
||||||
|
|
||||||
|
- Note:
|
||||||
|
Convenience for value(ofAttribute: String)
|
||||||
|
|
||||||
|
- parameter attr: The attribute to deserialize
|
||||||
|
- throws: an XMLDeserializationError if there is a problem with deserialization
|
||||||
|
- returns: The deserialized `T` value
|
||||||
|
*/
|
||||||
|
func value<T: XMLAttributeDeserializable, A: RawRepresentable>(ofAttribute attr: A) throws -> T where A.RawValue == String {
|
||||||
|
try value(ofAttribute: attr.rawValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Attempts to deserialize the value of the specified attribute of the current XMLIndexer
|
||||||
|
element to `T?` using a String backed RawRepresentable (E.g. `String` backed `enum` cases)
|
||||||
|
|
||||||
|
- Note:
|
||||||
|
Convenience for value(ofAttribute: String)
|
||||||
|
|
||||||
|
- parameter attr: The attribute to deserialize
|
||||||
|
- returns: The deserialized `T?` value, or nil if the attribute does not exist
|
||||||
|
*/
|
||||||
|
func value<T: XMLAttributeDeserializable, A: RawRepresentable>(ofAttribute attr: A) -> T? where A.RawValue == String {
|
||||||
|
value(ofAttribute: attr.rawValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Attempts to deserialize the value of the specified attribute of the current XMLIndexer
|
||||||
|
element to `[T]` using a String backed RawRepresentable (E.g. `String` backed `enum` cases)
|
||||||
|
|
||||||
|
- Note:
|
||||||
|
Convenience for value(ofAttribute: String)
|
||||||
|
|
||||||
|
- parameter attr: The attribute to deserialize
|
||||||
|
- throws: an XMLDeserializationError if there is a problem with deserialization
|
||||||
|
- returns: The deserialized `[T]` value
|
||||||
|
*/
|
||||||
|
func value<T: XMLAttributeDeserializable, A: RawRepresentable>(ofAttribute attr: A) throws -> [T] where A.RawValue == String {
|
||||||
|
try value(ofAttribute: attr.rawValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Attempts to deserialize the value of the specified attribute of the current XMLIndexer
|
||||||
|
element to `[T]?` using a String backed RawRepresentable (E.g. `String` backed `enum` cases)
|
||||||
|
|
||||||
|
- Note:
|
||||||
|
Convenience for value(ofAttribute: String)
|
||||||
|
|
||||||
|
- parameter attr: The attribute to deserialize
|
||||||
|
- throws: an XMLDeserializationError if there is a problem with deserialization
|
||||||
|
- returns: The deserialized `[T]?` value
|
||||||
|
*/
|
||||||
|
func value<T: XMLAttributeDeserializable, A: RawRepresentable>(ofAttribute attr: A) throws -> [T]? where A.RawValue == String {
|
||||||
|
try value(ofAttribute: attr.rawValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Attempts to deserialize the value of the specified attribute of the current XMLIndexer
|
||||||
|
element to `[T?]` using a String backed RawRepresentable (E.g. `String` backed `enum` cases)
|
||||||
|
|
||||||
|
- Note:
|
||||||
|
Convenience for value(ofAttribute: String)
|
||||||
|
|
||||||
|
- parameter attr: The attribute to deserialize
|
||||||
|
- throws: an XMLDeserializationError if there is a problem with deserialization
|
||||||
|
- returns: The deserialized `[T?]` value
|
||||||
|
*/
|
||||||
|
func value<T: XMLAttributeDeserializable, A: RawRepresentable>(ofAttribute attr: A) throws -> [T?] where A.RawValue == String {
|
||||||
|
try value(ofAttribute: attr.rawValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - XMLElement Extensions
|
// MARK: - XMLElement Extensions
|
||||||
|
|
||||||
extension XMLElement {
|
extension XMLElement {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Attempts to deserialize the specified attribute of the current XMLElement to `T`
|
Attempts to deserialize the specified attribute of the current XMLElement to `T`
|
||||||
|
|
||||||
@ -405,7 +563,9 @@ extension XMLElement {
|
|||||||
*/
|
*/
|
||||||
public func value<T: XMLAttributeDeserializable>(ofAttribute attr: String) throws -> T {
|
public func value<T: XMLAttributeDeserializable>(ofAttribute attr: String) throws -> T {
|
||||||
if let attr = self.attribute(by: attr) {
|
if let attr = self.attribute(by: attr) {
|
||||||
return try T.deserialize(attr)
|
let deserialized = try T.deserialize(attr)
|
||||||
|
try deserialized.validate()
|
||||||
|
return deserialized
|
||||||
} else {
|
} else {
|
||||||
throw XMLDeserializationError.attributeDoesNotExist(element: self, attribute: attr)
|
throw XMLDeserializationError.attributeDoesNotExist(element: self, attribute: attr)
|
||||||
}
|
}
|
||||||
@ -419,7 +579,9 @@ extension XMLElement {
|
|||||||
*/
|
*/
|
||||||
public func value<T: XMLAttributeDeserializable>(ofAttribute attr: String) -> T? {
|
public func value<T: XMLAttributeDeserializable>(ofAttribute attr: String) -> T? {
|
||||||
if let attr = self.attribute(by: attr) {
|
if let attr = self.attribute(by: attr) {
|
||||||
return try? T.deserialize(attr)
|
let deserialized = try? T.deserialize(attr)
|
||||||
|
if deserialized != nil { try? deserialized?.validate() }
|
||||||
|
return deserialized
|
||||||
} else {
|
} else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -441,6 +603,41 @@ extension XMLElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: String RawRepresentable
|
||||||
|
|
||||||
|
/*: Provides XMLElement XMLAttributeDeserializable deserialization from String backed RawRepresentables
|
||||||
|
Added by [PeeJWeeJ](https://github.com/PeeJWeeJ) */
|
||||||
|
public extension XMLElement {
|
||||||
|
/**
|
||||||
|
Attempts to deserialize the specified attribute of the current XMLElement to `T`
|
||||||
|
using a String backed RawRepresentable (E.g. `String` backed `enum` cases)
|
||||||
|
|
||||||
|
- Note:
|
||||||
|
Convenience for value(ofAttribute: String)
|
||||||
|
|
||||||
|
- parameter attr: The attribute to deserialize
|
||||||
|
- throws: an XMLDeserializationError if there is a problem with deserialization
|
||||||
|
- returns: The deserialized `T` value
|
||||||
|
*/
|
||||||
|
func value<T: XMLAttributeDeserializable, A: RawRepresentable>(ofAttribute attr: A) throws -> T where A.RawValue == String {
|
||||||
|
try value(ofAttribute: attr.rawValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Attempts to deserialize the specified attribute of the current XMLElement to `T?`
|
||||||
|
using a String backed RawRepresentable (E.g. `String` backed `enum` cases)
|
||||||
|
|
||||||
|
- Note:
|
||||||
|
Convenience for value(ofAttribute: String)
|
||||||
|
|
||||||
|
- parameter attr: The attribute to deserialize
|
||||||
|
- returns: The deserialized `T?` value, or nil if the attribute does not exist.
|
||||||
|
*/
|
||||||
|
func value<T: XMLAttributeDeserializable, A: RawRepresentable>(ofAttribute attr: A) -> T? where A.RawValue == String {
|
||||||
|
value(ofAttribute: attr.rawValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - XMLDeserializationError
|
// MARK: - XMLDeserializationError
|
||||||
|
|
||||||
/// The error that is thrown if there is a problem with deserialization
|
/// The error that is thrown if there is a problem with deserialization
|
||||||
@ -484,11 +681,11 @@ public enum XMLDeserializationError: Error, CustomStringConvertible {
|
|||||||
return "This node is invalid: \(node)"
|
return "This node is invalid: \(node)"
|
||||||
case .nodeHasNoValue:
|
case .nodeHasNoValue:
|
||||||
return "This node is empty"
|
return "This node is empty"
|
||||||
case .typeConversionFailed(let type, let node):
|
case let .typeConversionFailed(type, node):
|
||||||
return "Can't convert node \(node) to value of type \(type)"
|
return "Can't convert node \(node) to value of type \(type)"
|
||||||
case .attributeDoesNotExist(let element, let attribute):
|
case let .attributeDoesNotExist(element, attribute):
|
||||||
return "Element \(element) does not contain attribute: \(attribute)"
|
return "Element \(element) does not contain attribute: \(attribute)"
|
||||||
case .attributeDeserializationFailed(let type, let attribute):
|
case let .attributeDeserializationFailed(type, attribute):
|
||||||
return "Can't convert attribute \(attribute) to value of type \(type)"
|
return "Can't convert attribute \(attribute) to value of type \(type)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -506,7 +703,7 @@ extension String: XMLElementDeserializable, XMLAttributeDeserializable {
|
|||||||
- returns: the deserialized String value
|
- returns: the deserialized String value
|
||||||
*/
|
*/
|
||||||
public static func deserialize(_ element: XMLElement) -> String {
|
public static func deserialize(_ element: XMLElement) -> String {
|
||||||
return element.text
|
element.text
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -516,8 +713,10 @@ extension String: XMLElementDeserializable, XMLAttributeDeserializable {
|
|||||||
- returns: the deserialized String value
|
- returns: the deserialized String value
|
||||||
*/
|
*/
|
||||||
public static func deserialize(_ attribute: XMLAttribute) -> String {
|
public static func deserialize(_ attribute: XMLAttribute) -> String {
|
||||||
return attribute.text
|
attribute.text
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func validate() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Int: XMLElementDeserializable, XMLAttributeDeserializable {
|
extension Int: XMLElementDeserializable, XMLAttributeDeserializable {
|
||||||
@ -551,6 +750,8 @@ extension Int: XMLElementDeserializable, XMLAttributeDeserializable {
|
|||||||
}
|
}
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func validate() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Double: XMLElementDeserializable, XMLAttributeDeserializable {
|
extension Double: XMLElementDeserializable, XMLAttributeDeserializable {
|
||||||
@ -584,6 +785,8 @@ extension Double: XMLElementDeserializable, XMLAttributeDeserializable {
|
|||||||
}
|
}
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func validate() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Float: XMLElementDeserializable, XMLAttributeDeserializable {
|
extension Float: XMLElementDeserializable, XMLAttributeDeserializable {
|
||||||
@ -617,6 +820,8 @@ extension Float: XMLElementDeserializable, XMLAttributeDeserializable {
|
|||||||
}
|
}
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func validate() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Bool: XMLElementDeserializable, XMLAttributeDeserializable {
|
extension Bool: XMLElementDeserializable, XMLAttributeDeserializable {
|
||||||
@ -649,4 +854,6 @@ extension Bool: XMLElementDeserializable, XMLAttributeDeserializable {
|
|||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
// swiftlint:enable line_length
|
// swiftlint:enable line_length
|
||||||
|
|
||||||
|
public func validate() {}
|
||||||
}
|
}
|
36
Dependencies/SWXMLHash/shim.swift
vendored
Normal file
36
Dependencies/SWXMLHash/shim.swift
vendored
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
//
|
||||||
|
// shim.swift
|
||||||
|
// SWXMLHash
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 David Mohundro
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
|
||||||
|
#if (!swift(>=4.1) && swift(>=4.0)) || !swift(>=3.3)
|
||||||
|
|
||||||
|
extension Sequence {
|
||||||
|
func compactMap<ElementOfResult>(
|
||||||
|
_ transform: (Self.Element
|
||||||
|
) throws -> ElementOfResult?) rethrows -> [ElementOfResult] {
|
||||||
|
try flatMap(transform)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -147,15 +147,12 @@
|
|||||||
5713C4F51E5AE2C300BBA4D9 /* CombineAnimationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5713C4F41E5AE2C300BBA4D9 /* CombineAnimationTests.swift */; };
|
5713C4F51E5AE2C300BBA4D9 /* CombineAnimationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5713C4F41E5AE2C300BBA4D9 /* CombineAnimationTests.swift */; };
|
||||||
5713C4F71E5C34C700BBA4D9 /* SequenceAnimationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5713C4F61E5C34C700BBA4D9 /* SequenceAnimationTests.swift */; };
|
5713C4F71E5C34C700BBA4D9 /* SequenceAnimationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5713C4F61E5C34C700BBA4D9 /* SequenceAnimationTests.swift */; };
|
||||||
5713C4F91E5C3FEE00BBA4D9 /* DelayedAnimationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5713C4F81E5C3FEE00BBA4D9 /* DelayedAnimationTests.swift */; };
|
5713C4F91E5C3FEE00BBA4D9 /* DelayedAnimationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5713C4F81E5C3FEE00BBA4D9 /* DelayedAnimationTests.swift */; };
|
||||||
572CEFC71E2CED4B008C7C83 /* SWXMLHash+TypeConversion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 572CEFC51E2CED4B008C7C83 /* SWXMLHash+TypeConversion.swift */; };
|
|
||||||
572CEFC81E2CED4B008C7C83 /* SWXMLHash.swift in Sources */ = {isa = PBXBuildFile; fileRef = 572CEFC61E2CED4B008C7C83 /* SWXMLHash.swift */; };
|
|
||||||
57614AFD1F83D15600875933 /* Group.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57E5E1381E3B393900D1CB28 /* Group.swift */; };
|
57614AFD1F83D15600875933 /* Group.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57E5E1381E3B393900D1CB28 /* Group.swift */; };
|
||||||
57614AFE1F83D15600875933 /* TextRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57E5E1441E3B393900D1CB28 /* TextRenderer.swift */; };
|
57614AFE1F83D15600875933 /* TextRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57E5E1441E3B393900D1CB28 /* TextRenderer.swift */; };
|
||||||
57614AFF1F83D15600875933 /* CGFloat+Double.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57E5E14D1E3B393900D1CB28 /* CGFloat+Double.swift */; };
|
57614AFF1F83D15600875933 /* CGFloat+Double.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57E5E14D1E3B393900D1CB28 /* CGFloat+Double.swift */; };
|
||||||
57614B021F83D15600875933 /* RoundRect.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57E5E1341E3B393900D1CB28 /* RoundRect.swift */; };
|
57614B021F83D15600875933 /* RoundRect.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57E5E1341E3B393900D1CB28 /* RoundRect.swift */; };
|
||||||
57614B031F83D15600875933 /* UIImage2Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57900FF81EA0DEBF00809FFB /* UIImage2Image.swift */; };
|
57614B031F83D15600875933 /* UIImage2Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57900FF81EA0DEBF00809FFB /* UIImage2Image.swift */; };
|
||||||
57614B041F83D15600875933 /* SVGParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57E5E1471E3B393900D1CB28 /* SVGParser.swift */; };
|
57614B041F83D15600875933 /* SVGParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57E5E1471E3B393900D1CB28 /* SVGParser.swift */; };
|
||||||
57614B051F83D15600875933 /* SWXMLHash.swift in Sources */ = {isa = PBXBuildFile; fileRef = 572CEFC61E2CED4B008C7C83 /* SWXMLHash.swift */; };
|
|
||||||
57614B071F83D15600875933 /* RenderUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57E5E1421E3B393900D1CB28 /* RenderUtils.swift */; };
|
57614B071F83D15600875933 /* RenderUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57E5E1421E3B393900D1CB28 /* RenderUtils.swift */; };
|
||||||
57614B081F83D15600875933 /* FuncBounds.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57E5E0F11E3B393900D1CB28 /* FuncBounds.swift */; };
|
57614B081F83D15600875933 /* FuncBounds.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57E5E0F11E3B393900D1CB28 /* FuncBounds.swift */; };
|
||||||
57614B0A1F83D15600875933 /* DoubleInterpolation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57E5E0EC1E3B393900D1CB28 /* DoubleInterpolation.swift */; };
|
57614B0A1F83D15600875933 /* DoubleInterpolation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57E5E0EC1E3B393900D1CB28 /* DoubleInterpolation.swift */; };
|
||||||
@ -234,7 +231,6 @@
|
|||||||
57614B671F83D15600875933 /* ContentsInterpolation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57A27BCE1E44C4EC0057BD3A /* ContentsInterpolation.swift */; };
|
57614B671F83D15600875933 /* ContentsInterpolation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57A27BCE1E44C4EC0057BD3A /* ContentsInterpolation.swift */; };
|
||||||
57614B681F83D15600875933 /* GroupRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57E5E13E1E3B393900D1CB28 /* GroupRenderer.swift */; };
|
57614B681F83D15600875933 /* GroupRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57E5E13E1E3B393900D1CB28 /* GroupRenderer.swift */; };
|
||||||
57614B6B1F83D15600875933 /* NSTimer+Closure.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57E5E14E1E3B393900D1CB28 /* NSTimer+Closure.swift */; };
|
57614B6B1F83D15600875933 /* NSTimer+Closure.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57E5E14E1E3B393900D1CB28 /* NSTimer+Closure.swift */; };
|
||||||
57614B6C1F83D15600875933 /* SWXMLHash+TypeConversion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 572CEFC51E2CED4B008C7C83 /* SWXMLHash+TypeConversion.swift */; };
|
|
||||||
57614B6D1F83D15600875933 /* AnimationSequence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57E5E0FF1E3B393900D1CB28 /* AnimationSequence.swift */; };
|
57614B6D1F83D15600875933 /* AnimationSequence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57E5E0FF1E3B393900D1CB28 /* AnimationSequence.swift */; };
|
||||||
57614B6E1F83D15600875933 /* MorphingGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57E5E0FB1E3B393900D1CB28 /* MorphingGenerator.swift */; };
|
57614B6E1F83D15600875933 /* MorphingGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57E5E0FB1E3B393900D1CB28 /* MorphingGenerator.swift */; };
|
||||||
57614B6F1F83D15600875933 /* SVGConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57E5E1461E3B393900D1CB28 /* SVGConstants.swift */; };
|
57614B6F1F83D15600875933 /* SVGConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57E5E1461E3B393900D1CB28 /* SVGConstants.swift */; };
|
||||||
@ -681,6 +677,12 @@
|
|||||||
A7B47E44230EA402009DD7E5 /* Graphics_iOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = A718CD451F45C28700966E06 /* Graphics_iOS.swift */; };
|
A7B47E44230EA402009DD7E5 /* Graphics_iOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = A718CD451F45C28700966E06 /* Graphics_iOS.swift */; };
|
||||||
A7B47E45230EA404009DD7E5 /* Common_iOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = A718CD431F45C28200966E06 /* Common_iOS.swift */; };
|
A7B47E45230EA404009DD7E5 /* Common_iOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = A718CD431F45C28200966E06 /* Common_iOS.swift */; };
|
||||||
A7E675561EC4213500BD9ECB /* NodeBoundsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7E675551EC4213500BD9ECB /* NodeBoundsTests.swift */; };
|
A7E675561EC4213500BD9ECB /* NodeBoundsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7E675551EC4213500BD9ECB /* NodeBoundsTests.swift */; };
|
||||||
|
A7F46DE0270B0EE8008DA1DF /* XMLHash.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7F46DDD270B0EE8008DA1DF /* XMLHash.swift */; };
|
||||||
|
A7F46DE1270B0EE8008DA1DF /* XMLHash.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7F46DDD270B0EE8008DA1DF /* XMLHash.swift */; };
|
||||||
|
A7F46DE2270B0EE8008DA1DF /* shim.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7F46DDE270B0EE8008DA1DF /* shim.swift */; };
|
||||||
|
A7F46DE3270B0EE8008DA1DF /* shim.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7F46DDE270B0EE8008DA1DF /* shim.swift */; };
|
||||||
|
A7F46DE4270B0EE8008DA1DF /* XMLIndexer+XMLIndexerDeserializable.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7F46DDF270B0EE8008DA1DF /* XMLIndexer+XMLIndexerDeserializable.swift */; };
|
||||||
|
A7F46DE5270B0EE8008DA1DF /* XMLIndexer+XMLIndexerDeserializable.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7F46DDF270B0EE8008DA1DF /* XMLIndexer+XMLIndexerDeserializable.swift */; };
|
||||||
C410148E1F834D290022EE44 /* style.svg in Resources */ = {isa = PBXBuildFile; fileRef = C410148D1F834D280022EE44 /* style.svg */; };
|
C410148E1F834D290022EE44 /* style.svg in Resources */ = {isa = PBXBuildFile; fileRef = C410148D1F834D280022EE44 /* style.svg */; };
|
||||||
C4153A8F1F8793DE001BA5EE /* small-logo.png in Resources */ = {isa = PBXBuildFile; fileRef = C4153A8E1F8793DD001BA5EE /* small-logo.png */; };
|
C4153A8F1F8793DE001BA5EE /* small-logo.png in Resources */ = {isa = PBXBuildFile; fileRef = C4153A8E1F8793DD001BA5EE /* small-logo.png */; };
|
||||||
C46E83551F94B20E00208037 /* transform.svg in Resources */ = {isa = PBXBuildFile; fileRef = C46E83541F94B20E00208037 /* transform.svg */; };
|
C46E83551F94B20E00208037 /* transform.svg in Resources */ = {isa = PBXBuildFile; fileRef = C46E83541F94B20E00208037 /* transform.svg */; };
|
||||||
@ -859,8 +861,6 @@
|
|||||||
5713C4F41E5AE2C300BBA4D9 /* CombineAnimationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CombineAnimationTests.swift; sourceTree = "<group>"; };
|
5713C4F41E5AE2C300BBA4D9 /* CombineAnimationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CombineAnimationTests.swift; sourceTree = "<group>"; };
|
||||||
5713C4F61E5C34C700BBA4D9 /* SequenceAnimationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SequenceAnimationTests.swift; sourceTree = "<group>"; };
|
5713C4F61E5C34C700BBA4D9 /* SequenceAnimationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SequenceAnimationTests.swift; sourceTree = "<group>"; };
|
||||||
5713C4F81E5C3FEE00BBA4D9 /* DelayedAnimationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DelayedAnimationTests.swift; sourceTree = "<group>"; };
|
5713C4F81E5C3FEE00BBA4D9 /* DelayedAnimationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DelayedAnimationTests.swift; sourceTree = "<group>"; };
|
||||||
572CEFC51E2CED4B008C7C83 /* SWXMLHash+TypeConversion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SWXMLHash+TypeConversion.swift"; sourceTree = "<group>"; };
|
|
||||||
572CEFC61E2CED4B008C7C83 /* SWXMLHash.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SWXMLHash.swift; sourceTree = "<group>"; };
|
|
||||||
57614B791F83D15600875933 /* MacawOSX.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MacawOSX.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
57614B791F83D15600875933 /* MacawOSX.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MacawOSX.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
57614BD91F8739EE00875933 /* MacawView+PDF.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MacawView+PDF.swift"; sourceTree = "<group>"; };
|
57614BD91F8739EE00875933 /* MacawView+PDF.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MacawView+PDF.swift"; sourceTree = "<group>"; };
|
||||||
57900FF81EA0DEBF00809FFB /* UIImage2Image.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIImage2Image.swift; sourceTree = "<group>"; };
|
57900FF81EA0DEBF00809FFB /* UIImage2Image.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIImage2Image.swift; sourceTree = "<group>"; };
|
||||||
@ -1260,6 +1260,9 @@
|
|||||||
A74C832B229FB7690085A832 /* color-prop-04-t-manual-osx.svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "color-prop-04-t-manual-osx.svg"; sourceTree = "<group>"; };
|
A74C832B229FB7690085A832 /* color-prop-04-t-manual-osx.svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "color-prop-04-t-manual-osx.svg"; sourceTree = "<group>"; };
|
||||||
A74C832D229FBA4C0085A832 /* color-prop-04-t-manual-osx.reference */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "color-prop-04-t-manual-osx.reference"; sourceTree = "<group>"; };
|
A74C832D229FBA4C0085A832 /* color-prop-04-t-manual-osx.reference */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "color-prop-04-t-manual-osx.reference"; sourceTree = "<group>"; };
|
||||||
A7E675551EC4213500BD9ECB /* NodeBoundsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = NodeBoundsTests.swift; path = Bounds/NodeBoundsTests.swift; sourceTree = "<group>"; };
|
A7E675551EC4213500BD9ECB /* NodeBoundsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = NodeBoundsTests.swift; path = Bounds/NodeBoundsTests.swift; sourceTree = "<group>"; };
|
||||||
|
A7F46DDD270B0EE8008DA1DF /* XMLHash.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XMLHash.swift; sourceTree = "<group>"; };
|
||||||
|
A7F46DDE270B0EE8008DA1DF /* shim.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = shim.swift; sourceTree = "<group>"; };
|
||||||
|
A7F46DDF270B0EE8008DA1DF /* XMLIndexer+XMLIndexerDeserializable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "XMLIndexer+XMLIndexerDeserializable.swift"; sourceTree = "<group>"; };
|
||||||
C410148D1F834D280022EE44 /* style.svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = style.svg; sourceTree = "<group>"; };
|
C410148D1F834D280022EE44 /* style.svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = style.svg; sourceTree = "<group>"; };
|
||||||
C4153A8E1F8793DD001BA5EE /* small-logo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "small-logo.png"; sourceTree = "<group>"; };
|
C4153A8E1F8793DD001BA5EE /* small-logo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "small-logo.png"; sourceTree = "<group>"; };
|
||||||
C43B064C1F9738EF00787A35 /* clip.svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = clip.svg; sourceTree = "<group>"; };
|
C43B064C1F9738EF00787A35 /* clip.svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = clip.svg; sourceTree = "<group>"; };
|
||||||
@ -1448,8 +1451,9 @@
|
|||||||
572CEFC41E2CED4B008C7C83 /* SWXMLHash */ = {
|
572CEFC41E2CED4B008C7C83 /* SWXMLHash */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
572CEFC51E2CED4B008C7C83 /* SWXMLHash+TypeConversion.swift */,
|
A7F46DDE270B0EE8008DA1DF /* shim.swift */,
|
||||||
572CEFC61E2CED4B008C7C83 /* SWXMLHash.swift */,
|
A7F46DDD270B0EE8008DA1DF /* XMLHash.swift */,
|
||||||
|
A7F46DDF270B0EE8008DA1DF /* XMLIndexer+XMLIndexerDeserializable.swift */,
|
||||||
);
|
);
|
||||||
path = SWXMLHash;
|
path = SWXMLHash;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -2697,7 +2701,6 @@
|
|||||||
5B6E194020AC58F900454E7E /* Stroke.swift in Sources */,
|
5B6E194020AC58F900454E7E /* Stroke.swift in Sources */,
|
||||||
57614B041F83D15600875933 /* SVGParser.swift in Sources */,
|
57614B041F83D15600875933 /* SVGParser.swift in Sources */,
|
||||||
A7B47E42230EA3FC009DD7E5 /* MDisplayLink_iOS.swift in Sources */,
|
A7B47E42230EA3FC009DD7E5 /* MDisplayLink_iOS.swift in Sources */,
|
||||||
57614B051F83D15600875933 /* SWXMLHash.swift in Sources */,
|
|
||||||
57614B071F83D15600875933 /* RenderUtils.swift in Sources */,
|
57614B071F83D15600875933 /* RenderUtils.swift in Sources */,
|
||||||
57614B081F83D15600875933 /* FuncBounds.swift in Sources */,
|
57614B081F83D15600875933 /* FuncBounds.swift in Sources */,
|
||||||
57614B0A1F83D15600875933 /* DoubleInterpolation.swift in Sources */,
|
57614B0A1F83D15600875933 /* DoubleInterpolation.swift in Sources */,
|
||||||
@ -2738,6 +2741,7 @@
|
|||||||
5B6E193020AC58F900454E7E /* LinearGradient.swift in Sources */,
|
5B6E193020AC58F900454E7E /* LinearGradient.swift in Sources */,
|
||||||
57614B261F83D15600875933 /* ShapeAnimation.swift in Sources */,
|
57614B261F83D15600875933 /* ShapeAnimation.swift in Sources */,
|
||||||
57614B271F83D15600875933 /* TransformInterpolation.swift in Sources */,
|
57614B271F83D15600875933 /* TransformInterpolation.swift in Sources */,
|
||||||
|
A7F46DE1270B0EE8008DA1DF /* XMLHash.swift in Sources */,
|
||||||
57614B281F83D15600875933 /* ShapeAnimationGenerator.swift in Sources */,
|
57614B281F83D15600875933 /* ShapeAnimationGenerator.swift in Sources */,
|
||||||
57614B291F83D15600875933 /* AnimationUtils.swift in Sources */,
|
57614B291F83D15600875933 /* AnimationUtils.swift in Sources */,
|
||||||
57614B2A1F83D15600875933 /* Polygon.swift in Sources */,
|
57614B2A1F83D15600875933 /* Polygon.swift in Sources */,
|
||||||
@ -2776,6 +2780,7 @@
|
|||||||
30FF496D215CF27E00FF653C /* MCAShapeLayerLineCap_macOS.swift in Sources */,
|
30FF496D215CF27E00FF653C /* MCAShapeLayerLineCap_macOS.swift in Sources */,
|
||||||
57614B491F83D15600875933 /* MView_macOS.swift in Sources */,
|
57614B491F83D15600875933 /* MView_macOS.swift in Sources */,
|
||||||
A7B47E3F230EA3F5009DD7E5 /* MCAShapeLayerLineCap_iOS.swift in Sources */,
|
A7B47E3F230EA3F5009DD7E5 /* MCAShapeLayerLineCap_iOS.swift in Sources */,
|
||||||
|
A7F46DE3270B0EE8008DA1DF /* shim.swift in Sources */,
|
||||||
5B6E192E20AC58F900454E7E /* Font.swift in Sources */,
|
5B6E192E20AC58F900454E7E /* Font.swift in Sources */,
|
||||||
5BFEF5D120B80A83008DAC11 /* ColorMatrixEffect.swift in Sources */,
|
5BFEF5D120B80A83008DAC11 /* ColorMatrixEffect.swift in Sources */,
|
||||||
57614B4A1F83D15600875933 /* Easing.swift in Sources */,
|
57614B4A1F83D15600875933 /* Easing.swift in Sources */,
|
||||||
@ -2810,6 +2815,7 @@
|
|||||||
5B9B970D2486506C00CAF2CE /* PathAnimationGenerator.swift in Sources */,
|
5B9B970D2486506C00CAF2CE /* PathAnimationGenerator.swift in Sources */,
|
||||||
57614B631F83D15600875933 /* Insets.swift in Sources */,
|
57614B631F83D15600875933 /* Insets.swift in Sources */,
|
||||||
3081E77E20DB58B100640F96 /* DescriptionExtensions.swift in Sources */,
|
3081E77E20DB58B100640F96 /* DescriptionExtensions.swift in Sources */,
|
||||||
|
A7F46DE5270B0EE8008DA1DF /* XMLIndexer+XMLIndexerDeserializable.swift in Sources */,
|
||||||
57614B641F83D15600875933 /* Rect.swift in Sources */,
|
57614B641F83D15600875933 /* Rect.swift in Sources */,
|
||||||
30FF4971215CF4CE00FF653C /* MCAMediaTimingFunctionName_macOS.swift in Sources */,
|
30FF4971215CF4CE00FF653C /* MCAMediaTimingFunctionName_macOS.swift in Sources */,
|
||||||
57614B651F83D15600875933 /* PathBuilder.swift in Sources */,
|
57614B651F83D15600875933 /* PathBuilder.swift in Sources */,
|
||||||
@ -2820,7 +2826,6 @@
|
|||||||
5B6E192A20AC58F900454E7E /* Align.swift in Sources */,
|
5B6E192A20AC58F900454E7E /* Align.swift in Sources */,
|
||||||
57614B6B1F83D15600875933 /* NSTimer+Closure.swift in Sources */,
|
57614B6B1F83D15600875933 /* NSTimer+Closure.swift in Sources */,
|
||||||
5B6E193620AC58F900454E7E /* Stop.swift in Sources */,
|
5B6E193620AC58F900454E7E /* Stop.swift in Sources */,
|
||||||
57614B6C1F83D15600875933 /* SWXMLHash+TypeConversion.swift in Sources */,
|
|
||||||
57614B6D1F83D15600875933 /* AnimationSequence.swift in Sources */,
|
57614B6D1F83D15600875933 /* AnimationSequence.swift in Sources */,
|
||||||
5B1A8C7720A15F7300E5FFAE /* SVGNodeLayout.swift in Sources */,
|
5B1A8C7720A15F7300E5FFAE /* SVGNodeLayout.swift in Sources */,
|
||||||
57614B6E1F83D15600875933 /* MorphingGenerator.swift in Sources */,
|
57614B6E1F83D15600875933 /* MorphingGenerator.swift in Sources */,
|
||||||
@ -2842,7 +2847,6 @@
|
|||||||
57900FF91EA0DEBF00809FFB /* UIImage2Image.swift in Sources */,
|
57900FF91EA0DEBF00809FFB /* UIImage2Image.swift in Sources */,
|
||||||
57E5E1AB1E3B393900D1CB28 /* SVGParser.swift in Sources */,
|
57E5E1AB1E3B393900D1CB28 /* SVGParser.swift in Sources */,
|
||||||
5B6E193F20AC58F900454E7E /* Stroke.swift in Sources */,
|
5B6E193F20AC58F900454E7E /* Stroke.swift in Sources */,
|
||||||
572CEFC81E2CED4B008C7C83 /* SWXMLHash.swift in Sources */,
|
|
||||||
57E5E1A71E3B393900D1CB28 /* RenderUtils.swift in Sources */,
|
57E5E1A71E3B393900D1CB28 /* RenderUtils.swift in Sources */,
|
||||||
57E5E1601E3B393900D1CB28 /* FuncBounds.swift in Sources */,
|
57E5E1601E3B393900D1CB28 /* FuncBounds.swift in Sources */,
|
||||||
A718CD481F45C28700966E06 /* MView_iOS.swift in Sources */,
|
A718CD481F45C28700966E06 /* MView_iOS.swift in Sources */,
|
||||||
@ -2884,6 +2888,7 @@
|
|||||||
57A27BD31E44C5570057BD3A /* ShapeAnimationGenerator.swift in Sources */,
|
57A27BD31E44C5570057BD3A /* ShapeAnimationGenerator.swift in Sources */,
|
||||||
57E5E1571E3B393900D1CB28 /* AnimationUtils.swift in Sources */,
|
57E5E1571E3B393900D1CB28 /* AnimationUtils.swift in Sources */,
|
||||||
30FF496F215CF3B000FF653C /* MCAMediaTimingFunctionName_iOS.swift in Sources */,
|
30FF496F215CF3B000FF653C /* MCAMediaTimingFunctionName_iOS.swift in Sources */,
|
||||||
|
A7F46DE0270B0EE8008DA1DF /* XMLHash.swift in Sources */,
|
||||||
57E5E1981E3B393900D1CB28 /* Polygon.swift in Sources */,
|
57E5E1981E3B393900D1CB28 /* Polygon.swift in Sources */,
|
||||||
57E5E1701E3B393900D1CB28 /* TransformAnimation.swift in Sources */,
|
57E5E1701E3B393900D1CB28 /* TransformAnimation.swift in Sources */,
|
||||||
57E5E16C1E3B393900D1CB28 /* CombineAnimation.swift in Sources */,
|
57E5E16C1E3B393900D1CB28 /* CombineAnimation.swift in Sources */,
|
||||||
@ -2922,6 +2927,7 @@
|
|||||||
5BFEF5CE20B80A83008DAC11 /* BlendEffect.swift in Sources */,
|
5BFEF5CE20B80A83008DAC11 /* BlendEffect.swift in Sources */,
|
||||||
A718CD501F45C28F00966E06 /* MView_macOS.swift in Sources */,
|
A718CD501F45C28F00966E06 /* MView_macOS.swift in Sources */,
|
||||||
57E5E1581E3B393900D1CB28 /* Easing.swift in Sources */,
|
57E5E1581E3B393900D1CB28 /* Easing.swift in Sources */,
|
||||||
|
A7F46DE2270B0EE8008DA1DF /* shim.swift in Sources */,
|
||||||
5BFEF5D020B80A83008DAC11 /* ColorMatrixEffect.swift in Sources */,
|
5BFEF5D020B80A83008DAC11 /* ColorMatrixEffect.swift in Sources */,
|
||||||
5B6E192D20AC58F900454E7E /* Font.swift in Sources */,
|
5B6E192D20AC58F900454E7E /* Font.swift in Sources */,
|
||||||
57E5E1971E3B393900D1CB28 /* Point.swift in Sources */,
|
57E5E1971E3B393900D1CB28 /* Point.swift in Sources */,
|
||||||
@ -2956,6 +2962,7 @@
|
|||||||
3081E77D20DB58B100640F96 /* DescriptionExtensions.swift in Sources */,
|
3081E77D20DB58B100640F96 /* DescriptionExtensions.swift in Sources */,
|
||||||
57E5E19A1E3B393900D1CB28 /* Rect.swift in Sources */,
|
57E5E19A1E3B393900D1CB28 /* Rect.swift in Sources */,
|
||||||
57E5E1941E3B393900D1CB28 /* PathBuilder.swift in Sources */,
|
57E5E1941E3B393900D1CB28 /* PathBuilder.swift in Sources */,
|
||||||
|
A7F46DE4270B0EE8008DA1DF /* XMLIndexer+XMLIndexerDeserializable.swift in Sources */,
|
||||||
57E5E1761E3B393900D1CB28 /* PinchEvent.swift in Sources */,
|
57E5E1761E3B393900D1CB28 /* PinchEvent.swift in Sources */,
|
||||||
57A27BCF1E44C4EC0057BD3A /* ContentsInterpolation.swift in Sources */,
|
57A27BCF1E44C4EC0057BD3A /* ContentsInterpolation.swift in Sources */,
|
||||||
57E5E1A31E3B393900D1CB28 /* GroupRenderer.swift in Sources */,
|
57E5E1A31E3B393900D1CB28 /* GroupRenderer.swift in Sources */,
|
||||||
@ -2964,7 +2971,6 @@
|
|||||||
57E5E1B11E3B393900D1CB28 /* NSTimer+Closure.swift in Sources */,
|
57E5E1B11E3B393900D1CB28 /* NSTimer+Closure.swift in Sources */,
|
||||||
30FF4962215CE97300FF653C /* MCAMediaTimingFillMode_iOS.swift in Sources */,
|
30FF4962215CE97300FF653C /* MCAMediaTimingFillMode_iOS.swift in Sources */,
|
||||||
5B6E193520AC58F900454E7E /* Stop.swift in Sources */,
|
5B6E193520AC58F900454E7E /* Stop.swift in Sources */,
|
||||||
572CEFC71E2CED4B008C7C83 /* SWXMLHash+TypeConversion.swift in Sources */,
|
|
||||||
30FF496B215CF0ED00FF653C /* MCAShapeLayerLineCap_iOS.swift in Sources */,
|
30FF496B215CF0ED00FF653C /* MCAShapeLayerLineCap_iOS.swift in Sources */,
|
||||||
5BECDC7B222FE6DE009C8E6A /* PathAnimation.swift in Sources */,
|
5BECDC7B222FE6DE009C8E6A /* PathAnimation.swift in Sources */,
|
||||||
57E5E16B1E3B393900D1CB28 /* AnimationSequence.swift in Sources */,
|
57E5E16B1E3B393900D1CB28 /* AnimationSequence.swift in Sources */,
|
||||||
|
@ -69,7 +69,7 @@ class CSSParser {
|
|||||||
return .byTag(text)
|
return .byTag(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getStyles(element: SWXMLHash.XMLElement) -> [String: String] {
|
func getStyles(element: XMLHash.XMLElement) -> [String: String] {
|
||||||
var styleAttributes = [String: String]()
|
var styleAttributes = [String: String]()
|
||||||
|
|
||||||
if let styles = stylesByTag[element.name] {
|
if let styles = stylesByTag[element.name] {
|
||||||
|
@ -133,12 +133,12 @@ open class SVGParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fileprivate func parse() throws -> Group {
|
fileprivate func parse() throws -> Group {
|
||||||
let config = SWXMLHash.config { config in
|
let config = XMLHash.config { config in
|
||||||
config.shouldProcessNamespaces = true
|
config.shouldProcessNamespaces = true
|
||||||
}
|
}
|
||||||
let parsedXml = config.parse(xmlString)
|
let parsedXml = config.parse(xmlString)
|
||||||
|
|
||||||
var svgElement: SWXMLHash.XMLElement?
|
var svgElement: XMLHash.XMLElement?
|
||||||
for child in parsedXml.children {
|
for child in parsedXml.children {
|
||||||
if let element = child.element {
|
if let element = child.element {
|
||||||
if element.name == "svg" {
|
if element.name == "svg" {
|
||||||
@ -203,7 +203,7 @@ open class SVGParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fileprivate func parseViewBox(_ element: SWXMLHash.XMLElement) throws -> SVGNodeLayout? {
|
fileprivate func parseViewBox(_ element: XMLHash.XMLElement) throws -> SVGNodeLayout? {
|
||||||
let widthAttributeNil = element.allAttributes["width"] == nil
|
let widthAttributeNil = element.allAttributes["width"] == nil
|
||||||
let heightAttributeNil = element.allAttributes["height"] == nil
|
let heightAttributeNil = element.allAttributes["height"] == nil
|
||||||
let viewBoxAttributeNil = element.allAttributes["viewBox"] == nil
|
let viewBoxAttributeNil = element.allAttributes["viewBox"] == nil
|
||||||
@ -508,7 +508,7 @@ open class SVGParser {
|
|||||||
return Group(contents: groupNodes, place: getPosition(element), tag: getTag(element))
|
return Group(contents: groupNodes, place: getPosition(element), tag: getTag(element))
|
||||||
}
|
}
|
||||||
|
|
||||||
fileprivate func getPosition(_ element: SWXMLHash.XMLElement) -> Transform {
|
fileprivate func getPosition(_ element: XMLHash.XMLElement) -> Transform {
|
||||||
guard let transformAttribute = element.allAttributes["transform"]?.text else {
|
guard let transformAttribute = element.allAttributes["transform"]?.text else {
|
||||||
return Transform.identity
|
return Transform.identity
|
||||||
}
|
}
|
||||||
@ -666,7 +666,7 @@ open class SVGParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fileprivate func getStyleAttributes(_ groupAttributes: [String: String],
|
fileprivate func getStyleAttributes(_ groupAttributes: [String: String],
|
||||||
element: SWXMLHash.XMLElement) -> [String: String] {
|
element: XMLHash.XMLElement) -> [String: String] {
|
||||||
var styleAttributes: [String: String] = groupAttributes
|
var styleAttributes: [String: String] = groupAttributes
|
||||||
|
|
||||||
for (att, val) in styles.getStyles(element: element) {
|
for (att, val) in styles.getStyles(element: element) {
|
||||||
@ -876,7 +876,7 @@ open class SVGParser {
|
|||||||
return dashes
|
return dashes
|
||||||
}
|
}
|
||||||
|
|
||||||
fileprivate func getMatrix(_ element: SWXMLHash.XMLElement, attribute: String) -> [Double] {
|
fileprivate func getMatrix(_ element: XMLHash.XMLElement, attribute: String) -> [Double] {
|
||||||
var result = [Double]()
|
var result = [Double]()
|
||||||
if let values = element.allAttributes[attribute]?.text {
|
if let values = element.allAttributes[attribute]?.text {
|
||||||
let separatedValues = values.components(separatedBy: CharacterSet(charactersIn: " ,"))
|
let separatedValues = values.components(separatedBy: CharacterSet(charactersIn: " ,"))
|
||||||
@ -896,7 +896,7 @@ open class SVGParser {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
fileprivate func getTag(_ element: SWXMLHash.XMLElement) -> [String] {
|
fileprivate func getTag(_ element: XMLHash.XMLElement) -> [String] {
|
||||||
let id = element.allAttributes["id"]?.text
|
let id = element.allAttributes["id"]?.text
|
||||||
return id.map { [$0] } ?? []
|
return id.map { [$0] } ?? []
|
||||||
}
|
}
|
||||||
@ -1081,7 +1081,7 @@ open class SVGParser {
|
|||||||
return Align.min
|
return Align.min
|
||||||
}
|
}
|
||||||
|
|
||||||
fileprivate func parseSimpleText(_ text: SWXMLHash.XMLElement,
|
fileprivate func parseSimpleText(_ text: XMLHash.XMLElement,
|
||||||
textAnchor: String?,
|
textAnchor: String?,
|
||||||
fill: Fill?,
|
fill: Fill?,
|
||||||
stroke: Stroke?,
|
stroke: Stroke?,
|
||||||
@ -1156,7 +1156,7 @@ open class SVGParser {
|
|||||||
baseline: .alphabetic,
|
baseline: .alphabetic,
|
||||||
place: place,
|
place: place,
|
||||||
opacity: opacity)
|
opacity: opacity)
|
||||||
} else if let tspanElement = element as? SWXMLHash.XMLElement,
|
} else if let tspanElement = element as? XMLHash.XMLElement,
|
||||||
tspanElement.name == "tspan" {
|
tspanElement.name == "tspan" {
|
||||||
// parse as <tspan> element
|
// parse as <tspan> element
|
||||||
// ultimately skip it if it cannot be parsed
|
// ultimately skip it if it cannot be parsed
|
||||||
@ -1187,7 +1187,7 @@ open class SVGParser {
|
|||||||
return collection
|
return collection
|
||||||
}
|
}
|
||||||
|
|
||||||
fileprivate func parseTspan(_ element: SWXMLHash.XMLElement,
|
fileprivate func parseTspan(_ element: XMLHash.XMLElement,
|
||||||
withWhitespace: Bool = false,
|
withWhitespace: Bool = false,
|
||||||
textAnchor: String?,
|
textAnchor: String?,
|
||||||
fill: Fill?,
|
fill: Fill?,
|
||||||
@ -1242,7 +1242,7 @@ open class SVGParser {
|
|||||||
weight: getFontWeight(attributes) ?? fontWeight ?? "normal")
|
weight: getFontWeight(attributes) ?? fontWeight ?? "normal")
|
||||||
}
|
}
|
||||||
|
|
||||||
fileprivate func getTspanPosition(_ element: SWXMLHash.XMLElement,
|
fileprivate func getTspanPosition(_ element: XMLHash.XMLElement,
|
||||||
bounds: Rect,
|
bounds: Rect,
|
||||||
previousCollectedTspan: Node?,
|
previousCollectedTspan: Node?,
|
||||||
withWhitespace: inout Bool) -> Transform {
|
withWhitespace: inout Bool) -> Transform {
|
||||||
@ -1653,14 +1653,14 @@ open class SVGParser {
|
|||||||
return .none
|
return .none
|
||||||
}
|
}
|
||||||
|
|
||||||
fileprivate func getDoubleValue(_ element: SWXMLHash.XMLElement, attribute: String) -> Double? {
|
fileprivate func getDoubleValue(_ element: XMLHash.XMLElement, attribute: String) -> Double? {
|
||||||
guard let attributeValue = element.allAttributes[attribute]?.text else {
|
guard let attributeValue = element.allAttributes[attribute]?.text else {
|
||||||
return .none
|
return .none
|
||||||
}
|
}
|
||||||
return doubleFromString(attributeValue)
|
return doubleFromString(attributeValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
fileprivate func getDimensionValue(_ element: SWXMLHash.XMLElement, attribute: String) -> SVGLength? {
|
fileprivate func getDimensionValue(_ element: XMLHash.XMLElement, attribute: String) -> SVGLength? {
|
||||||
guard let attributeValue = element.allAttributes[attribute]?.text else {
|
guard let attributeValue = element.allAttributes[attribute]?.text else {
|
||||||
return .none
|
return .none
|
||||||
}
|
}
|
||||||
@ -1701,7 +1701,7 @@ open class SVGParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fileprivate func getDoubleValueFromPercentage(_ element: SWXMLHash.XMLElement, attribute: String) -> Double? {
|
fileprivate func getDoubleValueFromPercentage(_ element: XMLHash.XMLElement, attribute: String) -> Double? {
|
||||||
guard let attributeValue = element.allAttributes[attribute]?.text else {
|
guard let attributeValue = element.allAttributes[attribute]?.text else {
|
||||||
return .none
|
return .none
|
||||||
}
|
}
|
||||||
@ -1716,7 +1716,7 @@ open class SVGParser {
|
|||||||
return .none
|
return .none
|
||||||
}
|
}
|
||||||
|
|
||||||
fileprivate func getIntValue(_ element: SWXMLHash.XMLElement, attribute: String) -> Int? {
|
fileprivate func getIntValue(_ element: XMLHash.XMLElement, attribute: String) -> Int? {
|
||||||
if let attributeValue = element.allAttributes[attribute]?.text {
|
if let attributeValue = element.allAttributes[attribute]?.text {
|
||||||
if let doubleValue = Double(attributeValue) {
|
if let doubleValue = Double(attributeValue) {
|
||||||
return Int(doubleValue)
|
return Int(doubleValue)
|
||||||
|
Loading…
Reference in New Issue
Block a user