iphonetouchxml

Parsing multiple and multi-level nested elements with TouchXML


I have an XML with the following structure and I am trying to create my model object from this. Can someone please help me find a way to get these objects from the XML using TouchXML, NSMutableArray and NSMutableDictionay.

<?xml version="1.0" encoding="utf-8"?>
<response>
  <level1_items>
    <level1_item>
      <item_1>text</item_1>
      <item_2>text</item_2>
    </level1_item>
    <level1_item>
      <item_1>some text</item_1>
      <item_2>some more text</item_2>
  </level1_items>
  <items>
    <item>
      <child_items>
        <child_item>
          <leaf1>node text</leaf1>
          <leaf2>leaf text</leaf2>
          <leaf3>some text</leaf3>
        </child_item>
        <child_item>
          <leaf1>text</leaf1>
          <leaf2>leaf text</leaf2>
          <leaf3>more text</leaf3>
        </child_item>
      </child_items>
    </item>
    <item>
      <child_items>
        <child_item>
          <leaf1>node text</leaf1>
          <leaf2>leaf text</leaf2>
          <leaf3>some text</leaf3>
        </child_item>
        <child_item>
          <leaf1>text</leaf1>
          <leaf2>leaf text</leaf2>
          <leaf3>more text</leaf3>
        </child_item>
      </child_items>
    </item>
  </items>
</response>

I need to parse the <response> and its children.


Solution

  • First off, I have to say that your XML will be difficult to work with because you are trying to use a specific tag for each item in a list. For example:

      <level1_items>
        <level1_item>
          <item_1>text</item_1>
          <item_2>text</item_2>
        </level1_item>
        <level1_item>
          <item_1>some text</item_1>
          <item_2>some more text</item_2>
      </level1_items>
    

    the tags named <item_ 1>, <item_ 2> don't make sense as XML is intended to describe your data, not define it. If you have an entity called an item, you should probably just call it item and make the XML look like this:

      <level1_items>
        <level1_item>
          <item index="1">text</item>
          <item index="2">text</item>
        </level1_item>
        <level1_item>
          <item index="1">some text</item>
          <item index="2">some more text</item>
      </level1_items>
    

    Where each item has an index. For that matter, you could just load the document in your TouchXML CXMLDocument and grab the nodes you need with XPath and assume they're in the correct order ignoring the index= parameter I specified.

    The next issue is that converting XML to an NSDictioanry or NSArray of dictionaries is a pretty involved task and what you gain isn't worth the effort. Just load your XML into a CXMLDocument and then start obtaining nodes using XPath. Something like this:

    CXMLDocument *doc = [[CXMLDocument alloc] initWithXMLString:xmlString options:0 error:nil];
    
    // Returns all 'level1_item' nodes in an array    
    NSArray *nodes = [[doc rootElement] nodesForXPath:@"//response/level1_items/level1_item" error:nil];
    
    for (CXMLNode *itemNode in nodes)
    {
        for (CXMLNode *childNode in [itemNode children])
        {
            NSString *nodeName = [childNode name]; // should contain item_1 in first iteration
            NSString *nodeValue = [childNode stringValue]; // should contain 'text' in first iteration
            // Do something with the node data.
    
        }
    }
    

    I suggest trying to use the XML this way and then come back here and ask specific questions if you have problems.