XMLParser Delegate Methods not Called
up vote
2
down vote
favorite
I'm trying to abstract an XML parser into a custom class to run it from a VC. It compiles perfectly and my error handler shows up success. However, the actual delegate methods are skipped over. No data is getting parsed.
It all ran fine when I had every running it the VC, but I am now try to get away from spaghetti code.
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let parser = XMLParserHelper()
//try create file for persistent data
//CreatePlist.createPlist()
parser.runParser()
}
}
class XMLParserHelper: NSObject, XMLParserDelegate {
//list type variables to hold XML values (update list base on XML structure):
static var station: String = ""
static var latitude: String = ""
static var longitude: String = ""
private static var code: String = ""
private static var id: String = ""
//reusable method type veriales (do not touch)
static var strXMLData:String = ""
static var currentElement:String = ""
static var passData:Bool=false
static var passName:Bool=false
static var xmlParser = XMLParser()
//parser methods
func runParser(){
let xmlPath = Bundle.main.url(forResource: "station", withExtension: "xml")
let xmlParser = XMLParser(contentsOf: (xmlPath)!)
xmlParser?.delegate = self
let success:Bool = xmlParser!.parse()
xmlParser?.parse()
if success {
print("parse success!")
print(XMLParserHelper.currentElement)
} else {
print("parse failure!")
}
}
private static func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {
XMLParserHelper.currentElement=elementName;
if (elementName=="StationDesc" || elementName=="StationLatitude" || elementName=="StationLongitude" || elementName=="StationCode" || elementName=="StationId" ) {
if (elementName=="StationDesc") {
XMLParserHelper.passName=true;
}
XMLParserHelper.passData=true;
}
}
private static func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
XMLParserHelper.currentElement="";
if (elementName=="StationDesc" || elementName=="StationLatitude" || elementName=="StationLongitude" || elementName=="StationCode" || elementName=="StationId" ) {
if(elementName=="StationDesc") {
XMLParserHelper.passName=false;
}
XMLParserHelper.passData=false;
}
}
private static func parser(_ parser: XMLParser, foundCharacters string: String) {
if (XMLParserHelper.passName) {
XMLParserHelper.strXMLData=XMLParserHelper.strXMLData+"nn"+string
}
if (XMLParserHelper.passData) {
//ready content for codable struct
switch XMLParserHelper.currentElement {
case "StationDesc":
XMLParserHelper.station = string
case "StationLatitude":
XMLParserHelper.latitude = string
case "StationLongitude":
XMLParserHelper.longitude = string
case "StationCode":
XMLParserHelper.code = string
case "StationId":
XMLParserHelper.id = string
print(string)
default:
XMLParserHelper.id = string
}
}
}
func parser(_ parser: XMLParser, parseErrorOccurred parseError: Error) {
print("failure error: ", parseError)
}
}
ios swift nsxmlparser
add a comment |
up vote
2
down vote
favorite
I'm trying to abstract an XML parser into a custom class to run it from a VC. It compiles perfectly and my error handler shows up success. However, the actual delegate methods are skipped over. No data is getting parsed.
It all ran fine when I had every running it the VC, but I am now try to get away from spaghetti code.
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let parser = XMLParserHelper()
//try create file for persistent data
//CreatePlist.createPlist()
parser.runParser()
}
}
class XMLParserHelper: NSObject, XMLParserDelegate {
//list type variables to hold XML values (update list base on XML structure):
static var station: String = ""
static var latitude: String = ""
static var longitude: String = ""
private static var code: String = ""
private static var id: String = ""
//reusable method type veriales (do not touch)
static var strXMLData:String = ""
static var currentElement:String = ""
static var passData:Bool=false
static var passName:Bool=false
static var xmlParser = XMLParser()
//parser methods
func runParser(){
let xmlPath = Bundle.main.url(forResource: "station", withExtension: "xml")
let xmlParser = XMLParser(contentsOf: (xmlPath)!)
xmlParser?.delegate = self
let success:Bool = xmlParser!.parse()
xmlParser?.parse()
if success {
print("parse success!")
print(XMLParserHelper.currentElement)
} else {
print("parse failure!")
}
}
private static func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {
XMLParserHelper.currentElement=elementName;
if (elementName=="StationDesc" || elementName=="StationLatitude" || elementName=="StationLongitude" || elementName=="StationCode" || elementName=="StationId" ) {
if (elementName=="StationDesc") {
XMLParserHelper.passName=true;
}
XMLParserHelper.passData=true;
}
}
private static func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
XMLParserHelper.currentElement="";
if (elementName=="StationDesc" || elementName=="StationLatitude" || elementName=="StationLongitude" || elementName=="StationCode" || elementName=="StationId" ) {
if(elementName=="StationDesc") {
XMLParserHelper.passName=false;
}
XMLParserHelper.passData=false;
}
}
private static func parser(_ parser: XMLParser, foundCharacters string: String) {
if (XMLParserHelper.passName) {
XMLParserHelper.strXMLData=XMLParserHelper.strXMLData+"nn"+string
}
if (XMLParserHelper.passData) {
//ready content for codable struct
switch XMLParserHelper.currentElement {
case "StationDesc":
XMLParserHelper.station = string
case "StationLatitude":
XMLParserHelper.latitude = string
case "StationLongitude":
XMLParserHelper.longitude = string
case "StationCode":
XMLParserHelper.code = string
case "StationId":
XMLParserHelper.id = string
print(string)
default:
XMLParserHelper.id = string
}
}
}
func parser(_ parser: XMLParser, parseErrorOccurred parseError: Error) {
print("failure error: ", parseError)
}
}
ios swift nsxmlparser
My eyes hurt of all the repeating string literals :(
– J. Doe
Nov 10 at 12:56
Use a guard in runParser if xmlParser is nil do a fatalError
– David H
Nov 10 at 13:47
Unrelated to your issue but you don't need;
in Swift and you don't need( )
in anif
statement.
– rmaddy
Nov 10 at 16:05
add a comment |
up vote
2
down vote
favorite
up vote
2
down vote
favorite
I'm trying to abstract an XML parser into a custom class to run it from a VC. It compiles perfectly and my error handler shows up success. However, the actual delegate methods are skipped over. No data is getting parsed.
It all ran fine when I had every running it the VC, but I am now try to get away from spaghetti code.
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let parser = XMLParserHelper()
//try create file for persistent data
//CreatePlist.createPlist()
parser.runParser()
}
}
class XMLParserHelper: NSObject, XMLParserDelegate {
//list type variables to hold XML values (update list base on XML structure):
static var station: String = ""
static var latitude: String = ""
static var longitude: String = ""
private static var code: String = ""
private static var id: String = ""
//reusable method type veriales (do not touch)
static var strXMLData:String = ""
static var currentElement:String = ""
static var passData:Bool=false
static var passName:Bool=false
static var xmlParser = XMLParser()
//parser methods
func runParser(){
let xmlPath = Bundle.main.url(forResource: "station", withExtension: "xml")
let xmlParser = XMLParser(contentsOf: (xmlPath)!)
xmlParser?.delegate = self
let success:Bool = xmlParser!.parse()
xmlParser?.parse()
if success {
print("parse success!")
print(XMLParserHelper.currentElement)
} else {
print("parse failure!")
}
}
private static func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {
XMLParserHelper.currentElement=elementName;
if (elementName=="StationDesc" || elementName=="StationLatitude" || elementName=="StationLongitude" || elementName=="StationCode" || elementName=="StationId" ) {
if (elementName=="StationDesc") {
XMLParserHelper.passName=true;
}
XMLParserHelper.passData=true;
}
}
private static func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
XMLParserHelper.currentElement="";
if (elementName=="StationDesc" || elementName=="StationLatitude" || elementName=="StationLongitude" || elementName=="StationCode" || elementName=="StationId" ) {
if(elementName=="StationDesc") {
XMLParserHelper.passName=false;
}
XMLParserHelper.passData=false;
}
}
private static func parser(_ parser: XMLParser, foundCharacters string: String) {
if (XMLParserHelper.passName) {
XMLParserHelper.strXMLData=XMLParserHelper.strXMLData+"nn"+string
}
if (XMLParserHelper.passData) {
//ready content for codable struct
switch XMLParserHelper.currentElement {
case "StationDesc":
XMLParserHelper.station = string
case "StationLatitude":
XMLParserHelper.latitude = string
case "StationLongitude":
XMLParserHelper.longitude = string
case "StationCode":
XMLParserHelper.code = string
case "StationId":
XMLParserHelper.id = string
print(string)
default:
XMLParserHelper.id = string
}
}
}
func parser(_ parser: XMLParser, parseErrorOccurred parseError: Error) {
print("failure error: ", parseError)
}
}
ios swift nsxmlparser
I'm trying to abstract an XML parser into a custom class to run it from a VC. It compiles perfectly and my error handler shows up success. However, the actual delegate methods are skipped over. No data is getting parsed.
It all ran fine when I had every running it the VC, but I am now try to get away from spaghetti code.
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let parser = XMLParserHelper()
//try create file for persistent data
//CreatePlist.createPlist()
parser.runParser()
}
}
class XMLParserHelper: NSObject, XMLParserDelegate {
//list type variables to hold XML values (update list base on XML structure):
static var station: String = ""
static var latitude: String = ""
static var longitude: String = ""
private static var code: String = ""
private static var id: String = ""
//reusable method type veriales (do not touch)
static var strXMLData:String = ""
static var currentElement:String = ""
static var passData:Bool=false
static var passName:Bool=false
static var xmlParser = XMLParser()
//parser methods
func runParser(){
let xmlPath = Bundle.main.url(forResource: "station", withExtension: "xml")
let xmlParser = XMLParser(contentsOf: (xmlPath)!)
xmlParser?.delegate = self
let success:Bool = xmlParser!.parse()
xmlParser?.parse()
if success {
print("parse success!")
print(XMLParserHelper.currentElement)
} else {
print("parse failure!")
}
}
private static func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {
XMLParserHelper.currentElement=elementName;
if (elementName=="StationDesc" || elementName=="StationLatitude" || elementName=="StationLongitude" || elementName=="StationCode" || elementName=="StationId" ) {
if (elementName=="StationDesc") {
XMLParserHelper.passName=true;
}
XMLParserHelper.passData=true;
}
}
private static func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
XMLParserHelper.currentElement="";
if (elementName=="StationDesc" || elementName=="StationLatitude" || elementName=="StationLongitude" || elementName=="StationCode" || elementName=="StationId" ) {
if(elementName=="StationDesc") {
XMLParserHelper.passName=false;
}
XMLParserHelper.passData=false;
}
}
private static func parser(_ parser: XMLParser, foundCharacters string: String) {
if (XMLParserHelper.passName) {
XMLParserHelper.strXMLData=XMLParserHelper.strXMLData+"nn"+string
}
if (XMLParserHelper.passData) {
//ready content for codable struct
switch XMLParserHelper.currentElement {
case "StationDesc":
XMLParserHelper.station = string
case "StationLatitude":
XMLParserHelper.latitude = string
case "StationLongitude":
XMLParserHelper.longitude = string
case "StationCode":
XMLParserHelper.code = string
case "StationId":
XMLParserHelper.id = string
print(string)
default:
XMLParserHelper.id = string
}
}
}
func parser(_ parser: XMLParser, parseErrorOccurred parseError: Error) {
print("failure error: ", parseError)
}
}
ios swift nsxmlparser
ios swift nsxmlparser
edited Nov 10 at 16:04
rmaddy
234k27305371
234k27305371
asked Nov 10 at 12:41
Frank Ferdinand McGovern
155
155
My eyes hurt of all the repeating string literals :(
– J. Doe
Nov 10 at 12:56
Use a guard in runParser if xmlParser is nil do a fatalError
– David H
Nov 10 at 13:47
Unrelated to your issue but you don't need;
in Swift and you don't need( )
in anif
statement.
– rmaddy
Nov 10 at 16:05
add a comment |
My eyes hurt of all the repeating string literals :(
– J. Doe
Nov 10 at 12:56
Use a guard in runParser if xmlParser is nil do a fatalError
– David H
Nov 10 at 13:47
Unrelated to your issue but you don't need;
in Swift and you don't need( )
in anif
statement.
– rmaddy
Nov 10 at 16:05
My eyes hurt of all the repeating string literals :(
– J. Doe
Nov 10 at 12:56
My eyes hurt of all the repeating string literals :(
– J. Doe
Nov 10 at 12:56
Use a guard in runParser if xmlParser is nil do a fatalError
– David H
Nov 10 at 13:47
Use a guard in runParser if xmlParser is nil do a fatalError
– David H
Nov 10 at 13:47
Unrelated to your issue but you don't need
;
in Swift and you don't need ( )
in an if
statement.– rmaddy
Nov 10 at 16:05
Unrelated to your issue but you don't need
;
in Swift and you don't need ( )
in an if
statement.– rmaddy
Nov 10 at 16:05
add a comment |
2 Answers
2
active
oldest
votes
up vote
2
down vote
accepted
To make XMLParserDelegate
methods work, all the methods needs to be non-static, non-private methods.
So, all the properties should also be non-static.
class XMLParserHelper: NSObject, XMLParserDelegate {
//list type variables to hold XML values (update list base on XML structure):
var station: String = ""
var latitude: String = ""
var longitude: String = ""
private var code: String = ""
private var id: String = ""
//reusable method type veriales (do not touch)
var strXMLData: String = ""
var currentElement: String = ""
var passData: Bool = false
var passName: Bool = false
//parser methods
func runParser() {
let xmlURL = Bundle.main.url(forResource: "station", withExtension: "xml")!
let xmlParser = XMLParser(contentsOf: xmlURL)!
xmlParser.delegate = self
let success = xmlParser.parse()
if success {
print("parse success!")
print(currentElement)
} else {
print("parse failure!")
}
}
//MARK: XMLParserDelegate methods
func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {
currentElement = elementName
if elementName == "StationDesc"
|| elementName == "StationLatitude"
|| elementName == "StationLongitude"
|| elementName == "StationCode"
|| elementName == "StationId"
{
if elementName == "StationDesc" {
passName = true
}
passData = true
}
}
func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
currentElement = ""
if elementName == "StationDesc"
|| elementName == "StationLatitude"
|| elementName == "StationLongitude"
|| elementName == "StationCode"
|| elementName == "StationId"
{
if elementName == "StationDesc" {
passName = false
}
passData = false
}
}
func parser(_ parser: XMLParser, foundCharacters string: String) {
if passName {
strXMLData = strXMLData+"nn"+string
}
if passData {
//ready content for codable struct
switch currentElement {
case "StationDesc":
station = string
case "StationLatitude":
latitude = string
case "StationLongitude":
longitude = string
case "StationCode":
code = string
case "StationId":
id = string
print(string)
default:
id = string
}
}
}
func parser(_ parser: XMLParser, parseErrorOccurred parseError: Error) {
print("failure error: ", parseError)
}
}
The XMLParser
just needs to be held while parse()
is running, so you have no need to declare xmlParser
as a property of XMLParserHelper
.
OOPer, you Gem, that worked perfectly - been struggling with this for some time so it was quite a feeling to see those parser methods getting called! I think I see now where I went wrong now, as my custom class was calling these parse methods I assumed them to type methods rather than instance methods (hence I marked them static/private, but as they are infact delegate methods they are not private or type methods.
– Frank Ferdinand McGovern
Nov 10 at 20:30
@FrankFerdinandMcGovern Please don't forget to indicate that your question has been solved by clicking the checkmark to the left of the most helpful answer.
– rmaddy
Nov 10 at 21:56
@maddy, thanks for reminder and pointer, quite new to SO, so was wondering about that - have updated accordingly
– Frank Ferdinand McGovern
Nov 11 at 7:57
add a comment |
up vote
0
down vote
You need a strong reference
class ViewController: UIViewController{
var parser:XMLParserHelper!
override func viewDidLoad() {
super.viewDidLoad()
parser = XMLParserHelper()
parser.runParser()
}
}
1
Good answer. With no strong reference, the parser will be dealloc'd before it can do its job.
– Matthew
Nov 10 at 14:30
This is not the issue sincerunParser
is not asynchronous.
– rmaddy
Nov 10 at 16:31
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
accepted
To make XMLParserDelegate
methods work, all the methods needs to be non-static, non-private methods.
So, all the properties should also be non-static.
class XMLParserHelper: NSObject, XMLParserDelegate {
//list type variables to hold XML values (update list base on XML structure):
var station: String = ""
var latitude: String = ""
var longitude: String = ""
private var code: String = ""
private var id: String = ""
//reusable method type veriales (do not touch)
var strXMLData: String = ""
var currentElement: String = ""
var passData: Bool = false
var passName: Bool = false
//parser methods
func runParser() {
let xmlURL = Bundle.main.url(forResource: "station", withExtension: "xml")!
let xmlParser = XMLParser(contentsOf: xmlURL)!
xmlParser.delegate = self
let success = xmlParser.parse()
if success {
print("parse success!")
print(currentElement)
} else {
print("parse failure!")
}
}
//MARK: XMLParserDelegate methods
func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {
currentElement = elementName
if elementName == "StationDesc"
|| elementName == "StationLatitude"
|| elementName == "StationLongitude"
|| elementName == "StationCode"
|| elementName == "StationId"
{
if elementName == "StationDesc" {
passName = true
}
passData = true
}
}
func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
currentElement = ""
if elementName == "StationDesc"
|| elementName == "StationLatitude"
|| elementName == "StationLongitude"
|| elementName == "StationCode"
|| elementName == "StationId"
{
if elementName == "StationDesc" {
passName = false
}
passData = false
}
}
func parser(_ parser: XMLParser, foundCharacters string: String) {
if passName {
strXMLData = strXMLData+"nn"+string
}
if passData {
//ready content for codable struct
switch currentElement {
case "StationDesc":
station = string
case "StationLatitude":
latitude = string
case "StationLongitude":
longitude = string
case "StationCode":
code = string
case "StationId":
id = string
print(string)
default:
id = string
}
}
}
func parser(_ parser: XMLParser, parseErrorOccurred parseError: Error) {
print("failure error: ", parseError)
}
}
The XMLParser
just needs to be held while parse()
is running, so you have no need to declare xmlParser
as a property of XMLParserHelper
.
OOPer, you Gem, that worked perfectly - been struggling with this for some time so it was quite a feeling to see those parser methods getting called! I think I see now where I went wrong now, as my custom class was calling these parse methods I assumed them to type methods rather than instance methods (hence I marked them static/private, but as they are infact delegate methods they are not private or type methods.
– Frank Ferdinand McGovern
Nov 10 at 20:30
@FrankFerdinandMcGovern Please don't forget to indicate that your question has been solved by clicking the checkmark to the left of the most helpful answer.
– rmaddy
Nov 10 at 21:56
@maddy, thanks for reminder and pointer, quite new to SO, so was wondering about that - have updated accordingly
– Frank Ferdinand McGovern
Nov 11 at 7:57
add a comment |
up vote
2
down vote
accepted
To make XMLParserDelegate
methods work, all the methods needs to be non-static, non-private methods.
So, all the properties should also be non-static.
class XMLParserHelper: NSObject, XMLParserDelegate {
//list type variables to hold XML values (update list base on XML structure):
var station: String = ""
var latitude: String = ""
var longitude: String = ""
private var code: String = ""
private var id: String = ""
//reusable method type veriales (do not touch)
var strXMLData: String = ""
var currentElement: String = ""
var passData: Bool = false
var passName: Bool = false
//parser methods
func runParser() {
let xmlURL = Bundle.main.url(forResource: "station", withExtension: "xml")!
let xmlParser = XMLParser(contentsOf: xmlURL)!
xmlParser.delegate = self
let success = xmlParser.parse()
if success {
print("parse success!")
print(currentElement)
} else {
print("parse failure!")
}
}
//MARK: XMLParserDelegate methods
func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {
currentElement = elementName
if elementName == "StationDesc"
|| elementName == "StationLatitude"
|| elementName == "StationLongitude"
|| elementName == "StationCode"
|| elementName == "StationId"
{
if elementName == "StationDesc" {
passName = true
}
passData = true
}
}
func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
currentElement = ""
if elementName == "StationDesc"
|| elementName == "StationLatitude"
|| elementName == "StationLongitude"
|| elementName == "StationCode"
|| elementName == "StationId"
{
if elementName == "StationDesc" {
passName = false
}
passData = false
}
}
func parser(_ parser: XMLParser, foundCharacters string: String) {
if passName {
strXMLData = strXMLData+"nn"+string
}
if passData {
//ready content for codable struct
switch currentElement {
case "StationDesc":
station = string
case "StationLatitude":
latitude = string
case "StationLongitude":
longitude = string
case "StationCode":
code = string
case "StationId":
id = string
print(string)
default:
id = string
}
}
}
func parser(_ parser: XMLParser, parseErrorOccurred parseError: Error) {
print("failure error: ", parseError)
}
}
The XMLParser
just needs to be held while parse()
is running, so you have no need to declare xmlParser
as a property of XMLParserHelper
.
OOPer, you Gem, that worked perfectly - been struggling with this for some time so it was quite a feeling to see those parser methods getting called! I think I see now where I went wrong now, as my custom class was calling these parse methods I assumed them to type methods rather than instance methods (hence I marked them static/private, but as they are infact delegate methods they are not private or type methods.
– Frank Ferdinand McGovern
Nov 10 at 20:30
@FrankFerdinandMcGovern Please don't forget to indicate that your question has been solved by clicking the checkmark to the left of the most helpful answer.
– rmaddy
Nov 10 at 21:56
@maddy, thanks for reminder and pointer, quite new to SO, so was wondering about that - have updated accordingly
– Frank Ferdinand McGovern
Nov 11 at 7:57
add a comment |
up vote
2
down vote
accepted
up vote
2
down vote
accepted
To make XMLParserDelegate
methods work, all the methods needs to be non-static, non-private methods.
So, all the properties should also be non-static.
class XMLParserHelper: NSObject, XMLParserDelegate {
//list type variables to hold XML values (update list base on XML structure):
var station: String = ""
var latitude: String = ""
var longitude: String = ""
private var code: String = ""
private var id: String = ""
//reusable method type veriales (do not touch)
var strXMLData: String = ""
var currentElement: String = ""
var passData: Bool = false
var passName: Bool = false
//parser methods
func runParser() {
let xmlURL = Bundle.main.url(forResource: "station", withExtension: "xml")!
let xmlParser = XMLParser(contentsOf: xmlURL)!
xmlParser.delegate = self
let success = xmlParser.parse()
if success {
print("parse success!")
print(currentElement)
} else {
print("parse failure!")
}
}
//MARK: XMLParserDelegate methods
func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {
currentElement = elementName
if elementName == "StationDesc"
|| elementName == "StationLatitude"
|| elementName == "StationLongitude"
|| elementName == "StationCode"
|| elementName == "StationId"
{
if elementName == "StationDesc" {
passName = true
}
passData = true
}
}
func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
currentElement = ""
if elementName == "StationDesc"
|| elementName == "StationLatitude"
|| elementName == "StationLongitude"
|| elementName == "StationCode"
|| elementName == "StationId"
{
if elementName == "StationDesc" {
passName = false
}
passData = false
}
}
func parser(_ parser: XMLParser, foundCharacters string: String) {
if passName {
strXMLData = strXMLData+"nn"+string
}
if passData {
//ready content for codable struct
switch currentElement {
case "StationDesc":
station = string
case "StationLatitude":
latitude = string
case "StationLongitude":
longitude = string
case "StationCode":
code = string
case "StationId":
id = string
print(string)
default:
id = string
}
}
}
func parser(_ parser: XMLParser, parseErrorOccurred parseError: Error) {
print("failure error: ", parseError)
}
}
The XMLParser
just needs to be held while parse()
is running, so you have no need to declare xmlParser
as a property of XMLParserHelper
.
To make XMLParserDelegate
methods work, all the methods needs to be non-static, non-private methods.
So, all the properties should also be non-static.
class XMLParserHelper: NSObject, XMLParserDelegate {
//list type variables to hold XML values (update list base on XML structure):
var station: String = ""
var latitude: String = ""
var longitude: String = ""
private var code: String = ""
private var id: String = ""
//reusable method type veriales (do not touch)
var strXMLData: String = ""
var currentElement: String = ""
var passData: Bool = false
var passName: Bool = false
//parser methods
func runParser() {
let xmlURL = Bundle.main.url(forResource: "station", withExtension: "xml")!
let xmlParser = XMLParser(contentsOf: xmlURL)!
xmlParser.delegate = self
let success = xmlParser.parse()
if success {
print("parse success!")
print(currentElement)
} else {
print("parse failure!")
}
}
//MARK: XMLParserDelegate methods
func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {
currentElement = elementName
if elementName == "StationDesc"
|| elementName == "StationLatitude"
|| elementName == "StationLongitude"
|| elementName == "StationCode"
|| elementName == "StationId"
{
if elementName == "StationDesc" {
passName = true
}
passData = true
}
}
func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
currentElement = ""
if elementName == "StationDesc"
|| elementName == "StationLatitude"
|| elementName == "StationLongitude"
|| elementName == "StationCode"
|| elementName == "StationId"
{
if elementName == "StationDesc" {
passName = false
}
passData = false
}
}
func parser(_ parser: XMLParser, foundCharacters string: String) {
if passName {
strXMLData = strXMLData+"nn"+string
}
if passData {
//ready content for codable struct
switch currentElement {
case "StationDesc":
station = string
case "StationLatitude":
latitude = string
case "StationLongitude":
longitude = string
case "StationCode":
code = string
case "StationId":
id = string
print(string)
default:
id = string
}
}
}
func parser(_ parser: XMLParser, parseErrorOccurred parseError: Error) {
print("failure error: ", parseError)
}
}
The XMLParser
just needs to be held while parse()
is running, so you have no need to declare xmlParser
as a property of XMLParserHelper
.
answered Nov 10 at 16:24
OOPer
33.3k46082
33.3k46082
OOPer, you Gem, that worked perfectly - been struggling with this for some time so it was quite a feeling to see those parser methods getting called! I think I see now where I went wrong now, as my custom class was calling these parse methods I assumed them to type methods rather than instance methods (hence I marked them static/private, but as they are infact delegate methods they are not private or type methods.
– Frank Ferdinand McGovern
Nov 10 at 20:30
@FrankFerdinandMcGovern Please don't forget to indicate that your question has been solved by clicking the checkmark to the left of the most helpful answer.
– rmaddy
Nov 10 at 21:56
@maddy, thanks for reminder and pointer, quite new to SO, so was wondering about that - have updated accordingly
– Frank Ferdinand McGovern
Nov 11 at 7:57
add a comment |
OOPer, you Gem, that worked perfectly - been struggling with this for some time so it was quite a feeling to see those parser methods getting called! I think I see now where I went wrong now, as my custom class was calling these parse methods I assumed them to type methods rather than instance methods (hence I marked them static/private, but as they are infact delegate methods they are not private or type methods.
– Frank Ferdinand McGovern
Nov 10 at 20:30
@FrankFerdinandMcGovern Please don't forget to indicate that your question has been solved by clicking the checkmark to the left of the most helpful answer.
– rmaddy
Nov 10 at 21:56
@maddy, thanks for reminder and pointer, quite new to SO, so was wondering about that - have updated accordingly
– Frank Ferdinand McGovern
Nov 11 at 7:57
OOPer, you Gem, that worked perfectly - been struggling with this for some time so it was quite a feeling to see those parser methods getting called! I think I see now where I went wrong now, as my custom class was calling these parse methods I assumed them to type methods rather than instance methods (hence I marked them static/private, but as they are infact delegate methods they are not private or type methods.
– Frank Ferdinand McGovern
Nov 10 at 20:30
OOPer, you Gem, that worked perfectly - been struggling with this for some time so it was quite a feeling to see those parser methods getting called! I think I see now where I went wrong now, as my custom class was calling these parse methods I assumed them to type methods rather than instance methods (hence I marked them static/private, but as they are infact delegate methods they are not private or type methods.
– Frank Ferdinand McGovern
Nov 10 at 20:30
@FrankFerdinandMcGovern Please don't forget to indicate that your question has been solved by clicking the checkmark to the left of the most helpful answer.
– rmaddy
Nov 10 at 21:56
@FrankFerdinandMcGovern Please don't forget to indicate that your question has been solved by clicking the checkmark to the left of the most helpful answer.
– rmaddy
Nov 10 at 21:56
@maddy, thanks for reminder and pointer, quite new to SO, so was wondering about that - have updated accordingly
– Frank Ferdinand McGovern
Nov 11 at 7:57
@maddy, thanks for reminder and pointer, quite new to SO, so was wondering about that - have updated accordingly
– Frank Ferdinand McGovern
Nov 11 at 7:57
add a comment |
up vote
0
down vote
You need a strong reference
class ViewController: UIViewController{
var parser:XMLParserHelper!
override func viewDidLoad() {
super.viewDidLoad()
parser = XMLParserHelper()
parser.runParser()
}
}
1
Good answer. With no strong reference, the parser will be dealloc'd before it can do its job.
– Matthew
Nov 10 at 14:30
This is not the issue sincerunParser
is not asynchronous.
– rmaddy
Nov 10 at 16:31
add a comment |
up vote
0
down vote
You need a strong reference
class ViewController: UIViewController{
var parser:XMLParserHelper!
override func viewDidLoad() {
super.viewDidLoad()
parser = XMLParserHelper()
parser.runParser()
}
}
1
Good answer. With no strong reference, the parser will be dealloc'd before it can do its job.
– Matthew
Nov 10 at 14:30
This is not the issue sincerunParser
is not asynchronous.
– rmaddy
Nov 10 at 16:31
add a comment |
up vote
0
down vote
up vote
0
down vote
You need a strong reference
class ViewController: UIViewController{
var parser:XMLParserHelper!
override func viewDidLoad() {
super.viewDidLoad()
parser = XMLParserHelper()
parser.runParser()
}
}
You need a strong reference
class ViewController: UIViewController{
var parser:XMLParserHelper!
override func viewDidLoad() {
super.viewDidLoad()
parser = XMLParserHelper()
parser.runParser()
}
}
answered Nov 10 at 12:55
Sh_Khan
33.7k41124
33.7k41124
1
Good answer. With no strong reference, the parser will be dealloc'd before it can do its job.
– Matthew
Nov 10 at 14:30
This is not the issue sincerunParser
is not asynchronous.
– rmaddy
Nov 10 at 16:31
add a comment |
1
Good answer. With no strong reference, the parser will be dealloc'd before it can do its job.
– Matthew
Nov 10 at 14:30
This is not the issue sincerunParser
is not asynchronous.
– rmaddy
Nov 10 at 16:31
1
1
Good answer. With no strong reference, the parser will be dealloc'd before it can do its job.
– Matthew
Nov 10 at 14:30
Good answer. With no strong reference, the parser will be dealloc'd before it can do its job.
– Matthew
Nov 10 at 14:30
This is not the issue since
runParser
is not asynchronous.– rmaddy
Nov 10 at 16:31
This is not the issue since
runParser
is not asynchronous.– rmaddy
Nov 10 at 16:31
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53239063%2fxmlparser-delegate-methods-not-called%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
My eyes hurt of all the repeating string literals :(
– J. Doe
Nov 10 at 12:56
Use a guard in runParser if xmlParser is nil do a fatalError
– David H
Nov 10 at 13:47
Unrelated to your issue but you don't need
;
in Swift and you don't need( )
in anif
statement.– rmaddy
Nov 10 at 16:05