NSXMLParser Simple Example

后端 未结 4 518
说谎
说谎 2020-12-24 10:50

Most of the examples of how to invoke the NSXMLParser are contained within complex projects involving Apps. What does a simple example that demonstrates the callbacks look l

相关标签:
4条回答
  • 2020-12-24 11:25

    As part of exploring the NSXMLParser I created the following really simple code.

    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
    

    I've posted it in the hope that it helps someone else.

    0 讨论(0)
  • 2020-12-24 11:28
    #import <Cocoa/Cocoa.h>
    
    @interface AppDelegate : NSObject <NSApplicationDelegate, NSXMLParserDelegate>
    @property (nonatomic, strong) NSMutableDictionary *dictXML;
    @property (nonatomic,strong) NSMutableArray *arrOfUpdateDictsByVersion;
    @property (nonatomic,strong) NSString *strElementBeingParsed;
    @property (nonatomic,strong) NSString *strElementFinishedParsing;
    
    @end
    
    
    #import "AppDelegate.h"
    
    @interface AppDelegate ()
    @property (weak) IBOutlet NSWindow *window;
    @end
    
    @implementation AppDelegate
    
    @synthesize dictXML;
    @synthesize arrOfUpdateDictsByVersion;
    
    @synthesize strElementBeingParsed;
    @synthesize strElementFinishedParsing;
    
    
    - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
        // Insert code here to initialize your application
    
        [self initializeTheArray];
        [self startParsingXML];
    }
    
    -(void)initializeTheArray{
        self.dictXML = [[NSMutableDictionary alloc] init];
        self.arrOfUpdateDictsByVersion = [[NSMutableArray alloc] init];
    }
    
    -(void)startParsingXML{
    //    NSXMLParser *xmlparser = [[NSXMLParser alloc] initWithContentsOfURL:[NSURL URLWithString:@"http://cdn.example.com/databaseupdate.xml"]];
        NSXMLParser *xmlparser = [[NSXMLParser alloc] initWithContentsOfURL:[NSURL fileURLWithPath:@"/Users/vkrmsinha/Desktop/xmlParse.xml"]];
        [xmlparser setDelegate:self];
        [xmlparser parse];
    }
    
    - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict;
    {
        // initial tag comes in here
        self.strElementBeingParsed = elementName;
        /*if([elementName isEqualToString:@"Version"]){
    
        }
        else if ([elementName isEqualToString:@"Update"]){
    
        }*/
    }
    
    - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string;
    {
    
        if(([string rangeOfCharacterFromSet:[NSCharacterSet newlineCharacterSet]].location != NSNotFound) && ![self.strElementBeingParsed isEqualToString:@"Update"])
            return;
    
        // middle part from between the start and end tags comes here
        if ([self.strElementBeingParsed isEqualToString:@"Update"]){
            NSMutableDictionary *dictUpdate = [NSMutableDictionary dictionary];
            [self.arrOfUpdateDictsByVersion addObject:dictUpdate];
        }
        else if ([self.strElementBeingParsed isEqualToString:@"UpdateType"]){
            NSMutableDictionary *dictUpdate = [self.arrOfUpdateDictsByVersion lastObject];
            NSMutableDictionary *dictUpd = [NSMutableDictionary dictionary];
            [dictUpd setValue:string forKey:@"UpdateType"];
            [dictUpdate setValue:dictUpd forKey:@"update"];
        }
        else if([self.strElementBeingParsed isEqualToString:@"Version"]){
            NSMutableDictionary *dictUpdate = [self.arrOfUpdateDictsByVersion lastObject];
            // WARNING: ASK IF NO TWO VERSION WILL BE SAME IN FUTURE
            [dictUpdate setValue:string forKey:@"version"];
        }
        else if ([self.strElementBeingParsed isEqualToString:@"FileName"]){
            NSMutableDictionary *dictUpdate = [self.arrOfUpdateDictsByVersion lastObject];
            NSMutableDictionary *dict = [dictUpdate objectForKey:@"update"];
            [dict setValue:string forKey:@"FileName"];
        }
        else if ([self.strElementBeingParsed isEqualToString:@"Hash"]){
            NSMutableDictionary *dictUpdate = [self.arrOfUpdateDictsByVersion lastObject];
            NSMutableDictionary *dict = [dictUpdate objectForKey:@"update"];
            [dict setValue:string forKey:@"Hash"];
        }
        else if ([self.strElementBeingParsed isEqualToString:@"DownloadURL"]){
            NSMutableDictionary *dictUpdate = [self.arrOfUpdateDictsByVersion lastObject];
            NSMutableDictionary *dict = [dictUpdate objectForKey:@"update"];
            [dict setValue:string forKey:@"DownloadURL"];
        }
        else if ([self.strElementBeingParsed isEqualToString:@"Size"]){
            NSMutableDictionary *dictUpdate = [self.arrOfUpdateDictsByVersion lastObject];
            NSMutableDictionary *dict = [dictUpdate objectForKey:@"update"];
            [dict setValue:string forKey:@"Size"];
        }
    
    }
    
    - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName;
    {
        // ending of tag comes in here
        self.strElementFinishedParsing = elementName;
        if([elementName isEqualToString:@"Update"]){
            [self.arrOfUpdateDictsByVersion sortUsingDescriptors:[NSArray arrayWithObjects:[NSSortDescriptor sortDescriptorWithKey:@"self.version" ascending:YES], nil]];
            NSLog(@"%@", [self.arrOfUpdateDictsByVersion lastObject]);
    
        }
        if([elementName isEqualToString:@"UpdateDetails"]){
            NSMutableDictionary *dict = [NSMutableDictionary dictionary];
            [dict setValue:[[self.arrOfUpdateDictsByVersion lastObject] objectForKey:@"version"] forKey:@"latestVer"];
            [dict setValue:[[self.arrOfUpdateDictsByVersion firstObject] objectForKey:@"version"] forKey:@"oldestVer"];
            [dict setValue:self.arrOfUpdateDictsByVersion forKey:@"arrOfUpdsByVer"];
            NSLog(@"%@", dict);
        }
    
    }
    
    - (void)applicationWillTerminate:(NSNotification *)aNotification {
        // Insert code here to tear down your application
    }
    
    
    <UpdateDetails xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
       <DatabaseUpdates>
        <Update>
         <UpdateType>CompleteDatabase</UpdateType>
         <Version>1</Version>
         <FileName>1completedatabase.zip</FileName>
         <Hash>ad94431d2fe4cd60eb3347fadaa45d88</Hash>
         <DownloadURL>
          http://www.example.com/download/new.xml
         </DownloadURL>
         <Size>2367008</Size>
        </Update>
    </DatabaseUpdates>
    </UpdateDetails>
    
    0 讨论(0)
  • 2020-12-24 11:42

    Swift 4 Example - Parsing Xib-file.

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

    Usage:

    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.
    
    0 讨论(0)
  • 2020-12-24 11:48

    Here is a Swift version of the original Objective-C code below.

    It was built and tested using XCode 7.3. In writing the delegate I found it quite handy to copy the function prototypes from the documentation. It is worth noting that Swift is currently a fairly rapidly moving target.

    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")
        }
    }
    
    0 讨论(0)
提交回复
热议问题