5

I have read many examples of how to get text out of xml files, but just don't get how to. Here is a sample xml file:

<?xml version="1.0" encoding="UTF-8"?>
<questions>
    <set>
        <question>Question</question>
        <answer>Answer</answer>
    </set>
</questions>

Using -(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI, what's the easiest way to get the values Question and Answer? I already have my parser delegate hooked up and all that blah.

blake305
  • 2,196
  • 3
  • 23
  • 52

4 Answers4

13

For implementing NSXMLParser you need to implement delegate method of it.

First of all initiate NSXMLParser in this manner.

- (void)viewDidLoad {

    [super viewDidLoad];

    rssOutputData = [[NSMutableArray alloc]init];

    //declare the object of allocated variable
    NSData *xmlData=[[NSData alloc]initWithContentsOfURL:[NSURL URLWithString:@""]];// URL that given to parse.

    //allocate memory for parser as well as 
    xmlParserObject =[[NSXMLParser alloc]initWithData:xmlData];
    [xmlParserObject setDelegate:self];

    //asking the xmlparser object to beggin with its parsing
    [xmlParserObject parse];

    //releasing the object of NSData as a part of memory management
    [xmlData release];

}
//-------------------------------------------------------------


-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *) namespaceURI qualifiedName:(NSString *)qName
   attributes: (NSDictionary *)attributeDict
{
    if( [elementName isEqualToString:@"question"])
    {

         strquestion = [[NSMutableString alloc] init];

    }
}


//-------------------------------------------------------------


-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
       // init the ad hoc string with the value     
     currentElementValue = [[NSMutableString alloc] initWithString:string];
  } else {
     // append value to the ad hoc string    
    [currentElementValue appendString:string];
  }
  NSLog(@"Processing value for : %@", string);
}


//-------------------------------------------------------------


-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
    if( [elementName isEqualToString:@"question"])
    {
        [strquestion setString:elementName];
    }

 [currentElementValue release];
  currentElementValue = nil;
}

The above delegate method is sent by a parser object to its delegate when it encounters an end of specific element. In this method didEndElement you will get value of question.

Bo Persson
  • 90,663
  • 31
  • 146
  • 203
Nirav Jain
  • 5,088
  • 5
  • 40
  • 61
  • 1
    An if condition is missed out in `foundCharacters` :) `if (currentElementValue == nil)` – GoodSp33d Mar 30 '14 at 15:56
  • Has anyone used this code recently? I'm getting 'use of undeclared identifier xmlParserObject' errors. Is there an IMPORT missing? – user3741598 Jul 15 '14 at 22:35
  • @user3741598 just do NSXMLParser* xmlParserObject. I think in the example code above the parser is declare in the header first, hence not needing to say its type. That's my guess at least. – Max von Hippel Dec 03 '16 at 09:50
  • @Nirav Can you please see my question http://stackoverflow.com/questions/43539307/how-to-post-string-with-special-character-and-thai-language-using-xml-parsing-in – Muju Apr 22 '17 at 05:00
3
// This one called out when it hit a starting tag on xml in your case <question>

  BOOL got = FALSE;

  - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI 

 {

      if([elementName isEqualToString:@"question"])
       {
         got = TRUE;
       }
}

// This is third one to called out which gives the end tag of xml in your case </question>


- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName



// This delegate is the second one to called out which gives the value of current read tag in xml

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

   if(got)
  {
    NSLog(@"your desired tag value %@",string);
    got = FALSE; 
  }
}
superGokuN
  • 1,399
  • 13
  • 28
2

You have to implement the callbacks for NSXMLParserDelegate

The key ones are:

// called when it found an element - in your example, question or answer
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI 

// called when it hits the closing of the element (question or answer)
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI

// called when it found the characters in the data of the element
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string

So, when you hit the elements, you can set state whether the parser is currently in the question or answer element (with an iVar) and then when you get called back with foundCharacters, based on the state you set when you hit the element, you know which variable (question or answer) to assign the data to.

Gandalf
  • 2,399
  • 2
  • 15
  • 19
bryanmac
  • 38,941
  • 11
  • 91
  • 99
2

You need to implement the method

-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string

Once you see the elements whose (inner)text you want to grab, set a flag in your program, and keep a string with the things that foundCharacters finds between the tags. Once you hit the didEndElement method, you can do what you want with the string and reset the flag.

For example

-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
  if (sawQuestion) {
    // need to check here that self->myString has been initialized
    [self->myString appendString:string];
 }
}

and in didEndElement you can reset the flag sawQuestion

ddodev
  • 131
  • 8