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)
}
}









share|improve this question
























  • 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 an if statement.
    – rmaddy
    Nov 10 at 16:05















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)
}
}









share|improve this question
























  • 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 an if statement.
    – rmaddy
    Nov 10 at 16:05













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)
}
}









share|improve this question















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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 an if statement.
    – rmaddy
    Nov 10 at 16:05


















  • 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 an if 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












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.






share|improve this answer





















  • 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




















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()
}
}





share|improve this answer

















  • 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 since runParser is not asynchronous.
    – rmaddy
    Nov 10 at 16:31











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














 

draft saved


draft discarded


















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

























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.






share|improve this answer





















  • 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

















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.






share|improve this answer





















  • 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















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.






share|improve this answer












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.







share|improve this answer












share|improve this answer



share|improve this answer










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




















  • 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














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()
}
}





share|improve this answer

















  • 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 since runParser is not asynchronous.
    – rmaddy
    Nov 10 at 16:31















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()
}
}





share|improve this answer

















  • 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 since runParser is not asynchronous.
    – rmaddy
    Nov 10 at 16:31













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()
}
}





share|improve this answer












You need a strong reference



class ViewController: UIViewController{
var parser:XMLParserHelper!
override func viewDidLoad() {
super.viewDidLoad()
parser = XMLParserHelper()
parser.runParser()
}
}






share|improve this answer












share|improve this answer



share|improve this answer










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 since runParser is not asynchronous.
    – rmaddy
    Nov 10 at 16:31














  • 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 since runParser 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


















 

draft saved


draft discarded



















































 


draft saved


draft discarded














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





















































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







Popular posts from this blog

Florida Star v. B. J. F.

Danny Elfman

Lugert, Oklahoma