views:

36

answers:

3

Using Objective C - I want to loop through an XML tree and display the full XML content at each instance of a specific node matching with a particular element name.

As an example - I am looking to get the XML (represented as an NSString) within each instance of element b. I can get the value if there is only a string in element b, but how do I get an NSString representation formatted as XML including all the element names?

<element a>
   <element b>
      <element c>
          some text 1
      </element c>
   </element b>
   <element b>
      <element c>
          some text 2
      </element c>
   </element b>
   <element b>
      <element c>
          some text 3
      </element c>
   </element b>
</element a>
+1  A: 

You can use NSXMLParser to do this. The three main sections of the class (1) check for opening tags:

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName 
  namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName 
  attributes:(NSDictionary *)attributeDict;

(2) grab the content within the node encountered:

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

and (3) store the data to an appropriate place of your choice on node completion:

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

Apple has an excellent guide covering NSXMLParser here

diatrevolo
Oh, wait. I completely misinterpreted your question. You are looking on ways to parse XML out of XML, so to speak. I guess using this standard implementation of NSXMLParser, you could reconstruct what you need by knowing what node you are on at any given time...a little heavy-handed, I guess.
diatrevolo
A: 

There are possibly three approaches I can think of, all of which have the pros and cons.

  1. Parse as a string. Depending on what exactly you want to extract, you could just use string manipulation code to search and extract the bits you want. This ignores the xml structure and reduces the problem to a simple string processing one. But may not be clever enough depending on the xml and the nodes you want.

  2. Code up a NSXMLParser to parse the xml string into some sort of datastructure (i.e. DOM), locate the nodes you want in it and then get them to generate out the xml. Again depending on what you want, this could be too heavy. COuld also mean a lot more coding.

  3. Download a library to do the dirty work for you. There are a variety around and I have one at (Shameless self promotion here) http://github.com/drekka/dXml which may help. It can certainly parse the xml into a DOM like data structure from which you can use XPath like queries to find the nodes and convert back to strings. The cons of this is that you are now using a third party library.

Derek Clarkson
Unless his target platform is OS X which has XML DOM classes built in.
JeremyP
Doh! I was assuming iPhone :-)
Derek Clarkson
A: 

I had a brainwave last night and here is the solution I came up with... seems a little inelegant, but it works.

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{

    if ([elementName isEqualToString:@"element b"])
        {
        area = [[NSMutableString alloc] init];
        current_element = [elementName copy];
        }
    else if ([current_element isEqualToString:@"element b"])
        {
            NSString *tag = [NSString stringWithFormat:@"<%@>", elementName];
            [area appendString:tag];
        }
    }

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
    if ([elementName isEqualToString:@"element b"])
    {
        NSLog(@"tag info: %@", area);
    }
    else if ([current_element isEqualToString:@"element b"])
    {
        NSString *tag = [NSString stringWithFormat:@"</%@>", elementName];
        [area appendString:tag];
    }
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
    if ([current_element isEqualToString:@"element b"]) {
        [area appendString:string];
    }
}
huevos de oro