Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>This is a common problem with parsers like this one, of "type SAX", where you have to manually keep track of the current depth of the XML tree you're in. The problem, as always, is that loading the entire tree in a DOM structure in memory can be impossible, depending on the size of the data you want to manipulate.</p> <p>The following code shows a class that does this job:</p> <pre><code>#import &lt;Foundation/Foundation.h&gt; @interface Test : NSObject &lt;NSXMLParserDelegate&gt; { @private NSXMLParser *xmlParser; NSInteger depth; NSMutableString *currentName; NSString *currentElement; } - (void)start; @end </code></pre> <p>This is the implementation:</p> <pre><code>#import "Test.h" @interface Test () - (void)showCurrentDepth; @end @implementation Test - (void)dealloc { [currentElement release]; [currentName release]; [xmlParser release]; [super dealloc]; } - (void)start { NSString *xml = @"&lt;?xml version=\"1.0\" encoding=\"UTF-8\" ?&gt;&lt;Node&gt;&lt;name&gt;Main&lt;/name&gt;&lt;Node&gt;&lt;name&gt;Child 1&lt;/name&gt;&lt;/Node&gt;&lt;Node&gt;&lt;name&gt;Child 2&lt;/name&gt;&lt;/Node&gt;&lt;/Node&gt;"; xmlParser = [[NSXMLParser alloc] initWithData:[xml dataUsingEncoding:NSUTF8StringEncoding]]; [xmlParser setDelegate:self]; [xmlParser setShouldProcessNamespaces:NO]; [xmlParser setShouldReportNamespacePrefixes:NO]; [xmlParser setShouldResolveExternalEntities:NO]; [xmlParser parse]; } #pragma mark - #pragma mark NSXMLParserDelegate methods - (void)parserDidStartDocument:(NSXMLParser *)parser { NSLog(@"Document started", nil); depth = 0; currentElement = nil; } - (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError { NSLog(@"Error: %@", [parseError localizedDescription]); } - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict { [currentElement release]; currentElement = [elementName copy]; if ([currentElement isEqualToString:@"Node"]) { ++depth; [self showCurrentDepth]; } else if ([currentElement isEqualToString:@"name"]) { [currentName release]; currentName = [[NSMutableString alloc] init]; } } - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName { if ([elementName isEqualToString:@"Node"]) { --depth; [self showCurrentDepth]; } else if ([elementName isEqualToString:@"name"]) { if (depth == 1) { NSLog(@"Outer name tag: %@", currentName); } else { NSLog(@"Inner name tag: %@", currentName); } } } - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string { if ([currentElement isEqualToString:@"name"]) { [currentName appendString:string]; } } - (void)parserDidEndDocument:(NSXMLParser *)parser { NSLog(@"Document finished", nil); } #pragma mark - #pragma mark Private methods - (void)showCurrentDepth { NSLog(@"Current depth: %d", depth); } @end </code></pre> <p>This is the result of running a command line tool that triggers the "start" method above:</p> <pre><code>Document started Current depth: 1 Outer name tag: Main Current depth: 2 Inner name tag: Child 1 Current depth: 1 Current depth: 2 Inner name tag: Child 2 Current depth: 1 Current depth: 0 Document finished </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload