-
Notifications
You must be signed in to change notification settings - Fork 90
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature: Set text, append element and ignore namespaces #64
Conversation
SwiftyXMLParser/XML.swift
Outdated
Global XML setting for ignoring namespaces. | ||
If set to true all accessors will ignore the first part of an element name up to a semicolon (:). | ||
*/ | ||
public static var ignoreNamespaces = false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ignoreNamespaces should be a local property. Could you place it on Element
class?
extension XML {
open class Element {
open var name: String
open var text: String?
open var attributes = [String: String]()
open var childElements = [Element]()
open var lineNumberStart = -1
open var lineNumberEnd = -1
open var CDATA: Data?
open var ignoreNamespaces: Bool // <-
public init(name: String, ignoreNamespaces: Bool = false, text: String? = nil, attributes: [String: String] = [:], childElements: [Element] = []) {
and set the boolean value in Parser
class
extension XML {
class Parser: NSObject, XMLParserDelegate {
// ...
init(ignoreNamespaces: Bool = false) {
self.ignoreNamespaces = ignoreNamespaces
trimmingManner = nil
documentRoot = Element(name: "XML.Parser.AbstructedDocumentRoot", ignoreNamespaces: ignoreNamespaces)
}
init(trimming manner: CharacterSet, ignoreNamespaces: Bool = false) {
self.ignoreNamespaces = ignoreNamespaces
trimmingManner = manner
documentRoot = Element(name: "XML.Parser.AbstructedDocumentRoot", ignoreNamespaces: ignoreNamespaces)
}
// MARK:- private
fileprivate var documentRoot: Element
fileprivate var stack = [Element]()
fileprivate let trimmingManner: CharacterSet?
fileprivate let ignoreNamespaces: Bool // <-
func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {
let node = Element(name: elementName, ignoreNamespaces: ignoreNamespaces) // <-
change XML
I/F.
open class XML {
// /**
// Global XML setting for ignoring namespaces.
// If set to true all accessors will ignore the first part of an element name up to a semicolon (:).
// */
// public static var ignoreNamespaces = false
/**
Interface to parse NSData
- parameter data:NSData XML document
- returns:Accessor object to access XML document
*/
open class func parse(_ data: Data, ignoreNamespaces: Bool = false) -> Accessor {
return Parser(ignoreNamespaces: ignoreNamespaces).parse(data)
}
/**
Interface to parse String
- Parameter str:String XML document
- Returns:Accessor object to access XML document
*/
open class func parse(_ str: String, ignoreNamespaces: Bool = false) throws -> Accessor { // <-
guard let data = str.data(using: String.Encoding.utf8) else {
throw XMLError.failToEncodeString
}
return Parser(ignoreNamespaces: ignoreNamespaces).parse(data)
}
/**
Interface to parse NSData
- parameter data:NSData XML document
- parameter manner:NSCharacterSet If you wannna trim Text, assign this arg
- returns:Accessor object to access XML document
*/
open class func parse(_ data: Data, trimming manner: CharacterSet, ignoreNamespaces: Bool = false) -> Accessor { // <-
return Parser(trimming: manner, ignoreNamespaces: ignoreNamespaces).parse(data)
}
/**
Interface to parse String
- Parameter str:String XML document
- parameter manner:NSCharacterSet If you wannna trim Text, assign this arg
- Returns:Accessor object to access XML document
*/
open class func parse(_ str: String, trimming manner: CharacterSet, ignoreNamespaces: Bool = false) throws -> Accessor { // <-
guard let data = str.data(using: String.Encoding.utf8) else {
throw XMLError.failToEncodeString
}
return Parser(trimming: manner, ignoreNamespaces: ignoreNamespaces).parse(data)
}
@mrotrifork We appreciate your contribution. |
…leanup initialisers
Good feedback. I moved ignoreNamespaces to live inside XML.Element which can be set via parse(). I also cleaned up some of the initialisers. |
This PR covers the following 3 features. Might have been better to split it in 3 pull requests, but let us see if we can go through them one by one and I will make the necessary adjustments:
Feature 1: Ability to get and set text and attributes on single element using the Accessor, and keep the modified elements when creating an xml document. The same small change could also be applied to other types than text/string. It requires that the accessor is not created as a constant.
Feature 2: Ability to append a new element to an accessor.
Feature 3: Global flag for ignoring namespaces when accessing elements. Currently I am using this framework with SOAP XML, which has dynamically prefixed namespaces on all elements.
Bugfix 1: XML documents are created with an extra space when no attributes are added for an element.
Bugfix 2: XML declaration prefix is not optional.
Bugfix 3: XML Element does not have a full initialiser.
All 3 features have corresponding unit tests. Let me know what you think.