【问题标题】:NSXMLParser Simple ExampleNSXMLParser 简单示例
【发布时间】:2014-03-14 13:01:28
【问题描述】:

关于如何调用 NSXMLParser 的大多数示例都包含在涉及应用程序的复杂项目中。演示回调的简单示例是什么样的。

【问题讨论】:

  • Stack Overflow 从根本上说绝对是一个问答网站。您可以回答自己的问题,但您仍应遵循网站的形式。您的帖子很有帮助(谢谢!),但它不符合 Stack Overflow 的意图。请不要如此防御,并根据 SO 实践重构您的帖子。
  • Noted 下次会坚持更多的问答风格。至于GitHub我不知道怎么用。
  • 您能否将解决方案复制到下面的答案中,以便我们对其进行投票并将其从未答复列表中删除?谢谢。

标签: objective-c xml swift nsxmlparser


【解决方案1】:

作为探索 NSXMLParser 的一部分,我创建了以下非常简单的代码。

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

我已经发布它,希望它可以帮助其他人。

【讨论】:

    【解决方案2】:

    下面是原始 Objective-C 代码的 Swift 版本。

    它是使用 XCode 7.3 构建和测试的。在编写委托时,我发现从文档中复制函数原型非常方便。值得注意的是,Swift 目前是一个移动速度相当快的目标。

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

    【讨论】:

      【解决方案3】:

      Swift 4 示例 - 解析 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
            }
         }
      }
      

      用法:

      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.
      

      【讨论】:

        【解决方案4】:
        #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>
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-09-18
          • 1970-01-01
          相关资源
          最近更新 更多