objective-c xml swift nsxmlparser

objective c - Ejemplo simple de NSXMLParser



objective-c swift (3)

Aquí hay una versión Swift del código Objective-C original a continuación.

Fue construido y probado usando XCode 7.3. Al escribir al delegado, me pareció muy útil copiar los prototipos de función de la documentación. Vale la pena señalar que Swift es actualmente un objetivo en movimiento bastante rápido.

main.swift

import Foundation // Let''s go print("Main: Started") // Try to load the file. Display the description of the error if one occurs var xmlData : NSData do { xmlData = try NSData(contentsOfFile: "/Users/amt/Documents/TestXml/Test.xml", options: .DataReadingMappedIfSafe) } catch let error as NSError { print("Main: /(error.description)") exit(1) } // Create a parser and point it at the NSData object containing // the file we just loaded var parser : NSXMLParser! = NSXMLParser(data: xmlData) // Create a parser delegate object and assign it to the parser // Beware the "weak" reference and don''t try to combine the two lines // of code into one unless you like EXC_BAD_ACCESS exceptions var parserDelegate : MyXmlParserDelegate = MyXmlParserDelegate() parser.delegate = parserDelegate // This example also illustrates some of the namespace functions defined in // the delegate protocol so enable namespace reporting to see them invoked parser.shouldReportNamespacePrefixes = true // Parse the document if !parser.parse() { // If parse() returned false then an error occurred so display is location // and details let error = parser.parserError let line = parser.lineNumber let col = parser.columnNumber print("Parsing failed at /(line):/(col): /(error?.localizedDescription)") } // All done print("Main: Ended") exit(0)

MyXmlParserDelegate.swift

import Foundation class MyXmlParserDelegate:NSObject, NSXMLParserDelegate { @objc func parserDidStartDocument(parser: NSXMLParser) { print("parserDidStartDocument") } @objc func parser(parser: NSXMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) { print("didStartElement --> /(elementName)") } @objc func parser(parser: NSXMLParser, foundCharacters string: String) { print("foundCharacters --> /(string)") } @objc func parser(parser: NSXMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) { print("didEndElement --> /(elementName)") } @objc func parser(parser: NSXMLParser, didStartMappingPrefix prefix: String, toURI namespaceURI: String) { print("didStartMappingPrefix --> Prefix: /(prefix) toURI: /(namespaceURI)") } @objc func parser(parser: NSXMLParser, didEndMappingPrefix prefix: String) { print("didEndMappingPrefix --> Prefix: /(prefix)") } @objc func parserDidEndDocument(parser: NSXMLParser) { print("parserDidEndDocument") } }

La mayoría de los ejemplos de cómo invocar NSXMLParser están contenidos en proyectos complejos que involucran aplicaciones. ¿Qué aspecto tiene un ejemplo simple que demuestra las devoluciones de llamada?


Como parte de la exploración de NSXMLParser, creé el siguiente código realmente simple.

main.m

int main(int argc, const char * argv[]) { @autoreleasepool { NSLog(@"Main Started"); NSError *error = nil; // Load the file and check the result NSData *data = [NSData dataWithContentsOfFile:@"/Users/Tim/Documents/MusicXml/Small.xml" options:NSDataReadingUncached error:&error]; if(error) { NSLog(@"Error %@", error); return 1; } // Create a parser and point it at the NSData object containing the file we just loaded NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data]; // Create an instance of our parser delegate and assign it to the parser MyXmlParserDelegate *parserDelegate = [[MyXmlParserDelegate alloc] init]; [parser setDelegate:parserDelegate]; // Invoke the parser and check the result [parser parse]; error = [parser parserError]; if(error) { NSLog(@"Error %@", error); return 1; } // All done NSLog(@"Main Ended"); } return 0; }

MyXmlParserDelegate.h

#import <Foundation/Foundation.h> @interface MyXmlParserDelegate : NSObject <NSXMLParserDelegate> @end

MyXmlParserDelegate.m

#import "MyXmlParserDelegate.h" @implementation MyXmlParserDelegate - (void) parserDidStartDocument:(NSXMLParser *)parser { NSLog(@"parserDidStartDocument"); } - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict { NSLog(@"didStartElement --> %@", elementName); } -(void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string { NSLog(@"foundCharacters --> %@", string); } - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName { NSLog(@"didEndElement --> %@", elementName); } - (void) parserDidEndDocument:(NSXMLParser *)parser { NSLog(@"parserDidEndDocument"); } @end

Lo publiqué con la esperanza de que ayude a alguien más.


Ejemplo de Swift 4: análisis del archivo Xib.

import Foundation class XMLTransformer: NSObject { private let parser: XMLParser private var stack = [Node]() private var tree: Node? init(data: Data) { parser = XMLParser(data: data) super.init() parser.delegate = self } } extension XMLTransformer { func transform() throws -> Node? { parser.parse() if let e = parser.parserError { throw e } assert(stack.isEmpty) assert(tree != nil) return tree } } extension XMLTransformer: XMLParserDelegate { func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) { guard let tag = Tag(rawValue: elementName) else { return } let node = Node(tag: tag, attributes: attributeDict, nodes: []) stack.append(node) } func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) { guard let tag = Tag(rawValue: elementName) else { return } let lastElement = stack.removeLast() assert(lastElement.tag == tag) if let last = stack.last { last.nodes += [lastElement] } else { tree = lastElement } } } extension XMLTransformer { enum Tag: String { case document case objects case tableViewCell, tableViewCellContentView case subviews case mapView case constraints, constraint case connections, outlet } } extension XMLTransformer { class Node { let tag: Tag let attributes: [String : String] var nodes: [Node] init(tag: Tag, attributes: [String : String], nodes: [Node] = []) { self.tag = tag self.attributes = attributes self.nodes = nodes } } }

Uso:

let data = try xib(named: "MapTableViewCell") let c = XMLTransformer(data: data) let tree = try c.transform() // Here you have parsed XML in a Tree representation.