كيفية استخدام NSXMLPARSER لتحليل عناصر الوالدين والطفل التي لها نفس الاسم

StackOverflow https://stackoverflow.com/questions/2005448

سؤال

هل لدى أي شخص فكرة حول كيفية تحليل XML التالي باستخدام فئة NSXMLPARSER التي يحركها الأحداث؟

<Node>
  <name> Main </name>
  <Node>
    <name> Child 1 </name>
  </Node>

  <Node>
    <name> Child 2 </name>
  </Node>
</Node>

أريد جمع جميع الأسماء الثلاثة من ملف XML هذا، هل من الممكن، أو لا بد لي من التغيير إلى تحليل الأشجار؟

هل كانت مفيدة؟

المحلول

هذه مشكلة شائعة مع المحللين مثل هذا واحد، من "النوع SAX"، حيث يتعين عليك تتبع عمق شجرة XML يدويا يدويا. المشكلة، كما هو الحال دائما، هي أن تحميل الشجرة بأكملها دائما يمكن أن يكون بنية DOM في الذاكرة مستحيلا، اعتمادا على حجم البيانات التي تريد التعامل معها.

يعرض التعليمات البرمجية التالية فئة تقوم بهذه المهمة:

#import <Foundation/Foundation.h>

@interface Test : NSObject <NSXMLParserDelegate> 
{
@private
    NSXMLParser *xmlParser;
    NSInteger depth;
    NSMutableString *currentName;
    NSString *currentElement;
}

- (void)start;

@end

هذا هو التنفيذ:

#import "Test.h"

@interface Test ()
- (void)showCurrentDepth;
@end


@implementation Test

- (void)dealloc
{
    [currentElement release];
    [currentName release];
    [xmlParser release];
    [super dealloc];
}

- (void)start
{
    NSString *xml = @"<?xml version=\"1.0\" encoding=\"UTF-8\" ?><Node><name>Main</name><Node><name>Child 1</name></Node><Node><name>Child 2</name></Node></Node>";
    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

هذه هي نتيجة تشغيل أداة سطر الأوامر تقوم بتشغيل طريقة "بدء" أعلاه:

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

نصائح أخرى

- (NSInteger)columnNumber

يمنحك مستوى التعشيش NSXMLParser

طريقة أسهل للغاية لحلها من الإجابة المقبولة، لملفات XML القصيرة:

مثال XML:

<cotacoes>
    <bovespa>
            <cotacao>50058</cotacao>
            <variacao>-0.16</variacao>
    </bovespa>
    <dolar>
            <cotacao>3.4610</cotacao>
            <variacao>+0.29</variacao>
    </dolar>
    <euro>
            <cotacao>3.7673</cotacao>
            <variacao>-0.25</variacao>
    </euro>
    <atualizacao>04/08/15 - 18:14</atualizacao>
</cotacoes>

تنفيذ عداد:

@implementation className{
    int parserCounter;
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    parserCounter++;

    NSLog(@"%d: %@",contadorParser,string);

    if (parserCounter == 3) doAnythingFor3;
    if (parserCounter == 5) doAnythingFor5;
    if (parserCounter == 9) doAnythingFor9;
    if (parserCounter == 11) doAnythingFor11;
    if (parserCounter == 15) doAnythingFor15;
    if (parserCounter == 17) doAnythingFor17;
    if (parserCounter == 20) doAnythingFor20;

}

كيف أعرف رقم الساحرة هي عقدة ساحرة؟ من خلال رؤية السجل. سيكون شيء مثل:

2015-08-04 23:36:08.070 Tesouro Direto[7252:1554402] 1:     
2015-08-04 23:36:08.070 Tesouro Direto[7252:1554402] 2:     
2015-08-04 23:36:08.071 Tesouro Direto[7252:1554402] 3:     50058
2015-08-04 23:36:08.105 Tesouro Direto[7252:1554402] 4:     
2015-08-04 23:36:08.105 Tesouro Direto[7252:1554402] 5:     -0.16
2015-08-04 23:36:08.131 Tesouro Direto[7252:1554402] 6:     
2015-08-04 23:36:08.132 Tesouro Direto[7252:1554402] 7:     
2015-08-04 23:36:08.132 Tesouro Direto[7252:1554402] 8:     
2015-08-04 23:36:08.132 Tesouro Direto[7252:1554402] 9:     3.4610
2015-08-04 23:36:08.156 Tesouro Direto[7252:1554402] 10:    
2015-08-04 23:36:08.156 Tesouro Direto[7252:1554402] 11:    +0.29   
2015-08-04 23:36:08.180 Tesouro Direto[7252:1554402] 12:    
2015-08-04 23:36:08.180 Tesouro Direto[7252:1554402] 13:    
2015-08-04 23:36:08.180 Tesouro Direto[7252:1554402] 14:    
2015-08-04 23:36:08.180 Tesouro Direto[7252:1554402] 15:    3.7673
2015-08-04 23:36:08.203 Tesouro Direto[7252:1554402] 16:    
2015-08-04 23:36:08.203 Tesouro Direto[7252:1554402] 17:    -0.25
2015-08-04 23:36:08.226 Tesouro Direto[7252:1554402] 18:    
2015-08-04 23:36:08.227 Tesouro Direto[7252:1554402] 19:    
2015-08-04 23:36:08.227 Tesouro Direto[7252:1554402] 20:    04/08/15   - 18:14
2015-08-04 23:36:08.227 Tesouro Direto[7252:1554402] 21: 

سوف تظهر لك السجل رقم ساحرة هو كل عقدة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top