Warning: join() [function.join]: Invalid arguments passed in /home/troyb/troybrant.net/blog/wp-content/themes/hybrid-hacked/hybrid-hacked/library/functions/breadcrumbs.php on line 79

Simple XML to NSDictionary Converter

For the past year or so, I’ve been very lucky. All the data I’ve had to deal with has been packaged in JSON, not XML. And what a glorious year it’s been. Instead of writing complex, single-use XML-parsing code, I’ve had the joy of using Stig Brautaset’s excellent JSON-framework to parse JSON. The framework is dead simple to use. Have some JSON? Throw some JSON at the framework, and viola! You get back an NSDictionary or an NSArray. Just one line of code, and you’re done. Simple, elegant, and completely opposite to the experience of parsing XML.

What’s the problem parsing XML? Well, first you have to set up your NSXMLParser. Then, make sure you’re set as the delegate. Then, override the necessary delegate methods (there are 14 relevant NSXMLParserDelegate methods, so choose wisely!). Then, initialize your NSMutableString to record the strings from the text nodes. Then, initialize your model objects from the XML as elements are pushed and popped in the didStart and didEnd methods. And don’t forget to update your objects with data in the attributes dictionary. And so on, and so on.

XML files, especially small XML files, should be as easy to parse as JSON.

Last week, when faced with the depressing task of writing my first XML parser this year, I wrote a general-purpose XML to NSDictionary parser instead. Throw some XML at it, and it spits out an NSDictionary.

How does it work? Here are the key ideas:

  1. XML elements map to key names in the dictionary
  2. Each element corresponds to a child dictionary
  3. Attribute key-value pairs are added to the element’s child dictionary
  4. Strings from text nodes are assigned to the child dictionary’s “text” key
  5. If an element name is encountered multiple times, the value of the element is set to an array of children dictionaries

This conversion is not without its flaws, but it should work pretty well for most XML files.

The Code

The parser consists of a single class, XMLReader. You can either pass it an XML string or an XML data object, and it will return the NSDictionary version of the XML. If the XML is malformed or the parser fails for any other reason, the NSError pointer you pass in will be populated with an NSError object.

Here’s the header file:

//
// XMLReader.h
//

#import <Foundation/Foundation.h>

@interface XMLReader : NSObject
{
    NSMutableArray *dictionaryStack;
    NSMutableString *textInProgress;
    NSError **errorPointer;
}

+ (NSDictionary *)dictionaryForXMLData:(NSData *)data error:(NSError **)errorPointer;
+ (NSDictionary *)dictionaryForXMLString:(NSString *)string error:(NSError **)errorPointer;

@end

And the implementation:

//
// XMLReader.m
//

#import "XMLReader.h"

NSString *const kXMLReaderTextNodeKey = @"text";

@interface XMLReader (Internal)

- (id)initWithError:(NSError **)error;
- (NSDictionary *)objectWithData:(NSData *)data;

@end

@implementation XMLReader

#pragma mark -
#pragma mark Public methods

+ (NSDictionary *)dictionaryForXMLData:(NSData *)data error:(NSError **)error
{
    XMLReader *reader = [[XMLReader alloc] initWithError:error];
    NSDictionary *rootDictionary = [reader objectWithData:data];
    [reader release];
    return rootDictionary;
}

+ (NSDictionary *)dictionaryForXMLString:(NSString *)string error:(NSError **)error
{
    NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
    return [XMLReader dictionaryForXMLData:data error:error];
}

#pragma mark -
#pragma mark Parsing

- (id)initWithError:(NSError **)error
{
    if (self = [super init])
    {
        errorPointer = error;
    }
    return self;
}

- (void)dealloc
{
    [dictionaryStack release];
    [textInProgress release];
    [super dealloc];
}

- (NSDictionary *)objectWithData:(NSData *)data
{
    // Clear out any old data
    [dictionaryStack release];
    [textInProgress release];
    
    dictionaryStack = [[NSMutableArray alloc] init];
    textInProgress = [[NSMutableString alloc] init];
    
    // Initialize the stack with a fresh dictionary
    [dictionaryStack addObject:[NSMutableDictionary dictionary]];
    
    // Parse the XML
    NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
    parser.delegate = self;
    BOOL success = [parser parse];
    
    // Return the stack’s root dictionary on success
    if (success)
    {
        NSDictionary *resultDict = [dictionaryStack objectAtIndex:0];
        return resultDict;
    }
    
    return nil;
}

#pragma mark -
#pragma mark NSXMLParserDelegate methods

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
    // Get the dictionary for the current level in the stack
    NSMutableDictionary *parentDict = [dictionaryStack lastObject];
    
    // Create the child dictionary for the new element, and initilaize it with the attributes
    NSMutableDictionary *childDict = [NSMutableDictionary dictionary];
    [childDict addEntriesFromDictionary:attributeDict];
    
    // If there’s already an item for this key, it means we need to create an array
    id existingValue = [parentDict objectForKey:elementName];
    if (existingValue)
    {
        NSMutableArray *array = nil;
        if ([existingValue isKindOfClass:[NSMutableArray class]])
        {
            // The array exists, so use it
            array = (NSMutableArray *) existingValue;
        }
        else
        {
            // Create an array if it doesn’t exist
            array = [NSMutableArray array];
            [array addObject:existingValue];
            
            // Replace the child dictionary with an array of children dictionaries
            [parentDict setObject:array forKey:elementName];
        }
        
        // Add the new child dictionary to the array
        [array addObject:childDict];
    }
    else
    {
        // No existing value, so update the dictionary
        [parentDict setObject:childDict forKey:elementName];
    }
    
    // Update the stack
    [dictionaryStack addObject:childDict];
}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
    // Update the parent dict with text info
    NSMutableDictionary *dictInProgress = [dictionaryStack lastObject];
    
    // Set the text property
    if ([textInProgress length] > 0)
    {
        // Get rid of leading + trailing whitespace
        [dictInProgress setObject:textInProgress forKey:kXMLReaderTextNodeKey];
        
        // Reset the text
        [textInProgress release];
        textInProgress = [[NSMutableString alloc] init];
    }
    
    // Pop the current dict
    [dictionaryStack removeLastObject];
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    // Build the text value
    [textInProgress appendString:string];
}

- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
{
    // Set the error pointer to the parser’s error object
    *errorPointer = parseError;
}

@end

The code works by keeping a stack of dictionaries, one for each level of the XML file. Each time a new tag is encountered, a child dictionary is pushed onto the stack. Each time a tag is closed, the dictionary is popped off the stack.

Arrays of elements are detected when the same key appears twice in the dictionary. For instance, if the XML is “<book><page>1</page><page>2</page></book>”, the first time the “page” element is encountered, a child dictionary will be set as the value for the “page” key. The next time the “page” element is encountered, we detect that there’s already a value for the “page” key, so we put both pages in an array and set the value of the “page” key to the array.

Note: One side effect of detecting arrays in this fashion is that the value for a key (say “page” in the example above), can sometimes be set to an NSArray but other times be set to an NSDictionary. For example, if the book contains a single page, “page” will be set to an NSDictionary. If the book contains 2 or more pages, “page” will be set to an NSArray. You will need to account for this when reading from the dictionary produced by dictionaryFromXMLString:error: and dictionaryFromXMLData:error:.

When the parser comes across a text node in the XML, it inserts a key into the dictionary named “text” and sets the value to the parsed string.

Note: Make sure the XML you’re parsing doesn’t contain a field named “text”! You can change it to a non-conflicting name by editing the kXMLReaderTextNodeKey constant at the top of XMLReader.m.

Using the Code

The conversion is best illustrated by an example. The snippet below defines an XML string that is converted into a dictionary using XMLReader:

//
// XML string from http://labs.adobe.com/technologies/spry/samples/data_region/NestedXMLDataSample.html
//
NSString *testXMLString = @"<items><item id=\"0001\" type=\"donut\"><name>Cake</name><ppu>0.55</ppu><batters><batter id=\"1001\">Regular</batter><batter id=\"1002\">Chocolate</batter><batter id=\"1003\">Blueberry</batter></batters><topping id=\"5001\">None</topping><topping id=\"5002\">Glazed</topping><topping id=\"5005\">Sugar</topping></item></items>";

// Parse the XML into a dictionary
NSError *parseError = nil;
NSDictionary *xmlDictionary = [XMLReader dictionaryForXMLString:testXMLString error:&parseError];

// Print the dictionary
NSLog(@"%@", xmlDictionary);

//
// testXMLString =
//    <items>
//        <item id=”0001″ type=”donut”>
//            <name>Cake</name>
//            <ppu>0.55</ppu>
//            <batters>
//                <batter id=”1001″>Regular</batter>
//                <batter id=”1002″>Chocolate</batter>
//                <batter id=”1003″>Blueberry</batter>
//            </batters>
//            <topping id=”5001″>None</topping>
//            <topping id=”5002″>Glazed</topping>
//            <topping id=”5005″>Sugar</topping>
//        </item>
//    </items>
//
// is converted into
//
// xmlDictionary = {
//    items = {
//        item = {
//            id = 0001;
//            type = donut;
//            name = {
//                text = Cake;
//            };
//            ppu = {
//                text = 0.55;
//            };
//            batters = {
//                batter = (
//                    {
//                        id = 1001;
//                        text = Regular;
//                    },
//                    {
//                        id = 1002;
//                        text = Chocolate;
//                    },
//                    {
//                        id = 1003;
//                        text = Blueberry;
//                    }
//                );
//            };
//            topping = (
//                {
//                    id = 5001;
//                    text = None;
//                },
//                {
//                    id = 5002;
//                    text = Glazed;
//                },
//                {
//                    id = 5005;
//                    text = Sugar;
//                }
//            );
//        };
//     };
// }
//

The mapping between XML and NSDictionary is shown in the comments above. Notice how the “batter” and “topping” keys are set to arrays since there were multiple “batter” and “topping” keys in the XML. Also, note how the attributes for elements are available in the element’s child dictionary. For instance, the “id” and “type” attributes for item “item” are keys in the “item” dictionary.

Download

You can download the XMLReader files here:

XMLReader.zip

Done and Done

XMLReader isn’t perfect by any stretch of the imagination, but hopefully it helps save you some pain and misery next time you need to parse an XML file in Objective-C.

46 Responses to “Simple XML to NSDictionary Converter”

  1. Awesome! Thanks for releasing this, makes me watt to write and share cool code. I’ve used your site a few times, you have some of the best stuff regarding in app purchase as well. Very exhaustive and informative. Looking forward to testing this out. Thanks again!

    –nick

  2. Somehow I can’t find the link to this code posted on Github, that would make sense, instead of a Zip file. People could contribute and all that ;)

  3. Just about the only thing that could make this cooler would be:

    + (NSDictionary *)dictionaryForXMLURL:(NSURL *)url error:(NSError **)errorPointer;

    Would make grabbing RSS feeds, or just about any other XML-based web content that much more streamlined :)

  4. Could you please tell me some dictionary methods to read the dictionary you are generating.
    My dictionary generated is:

    Menus = {
    Table1 = {
    Phone = {
    text = “\n (404) 371-1466″;
    };
    “Restaurant_Name” = {
    text = “\n \n CHICK-FIL-A”;
    };
    “Restaurant_id” = {
    text = “\n 2748″;
    };
    “billing_addr1″ = {
    text = “\n 105 EAST TRINITY PLACE”;
    };
    “billing_city” = {
    text = “\n DECATUR”;
    };
    “billing_state” = {
    text = “\n GA”;
    };
    “billing_zip_code” = {
    text = “\n 30030″;
    };
    text = “\n “;
    };
    text = “\n”;
    };
    }

    Now how to read Restaurant_Name from this dictionary?

  5. +1 on the github suggestion!

  6. @Abhi

    Say your dictionary is named xmlDictionary, then you would get the Restaurant_Name value like this:

    NSString *restaurantName = [[[[xmlDictionary objectForKey:@"Menus"] objectForKey:@”Table1″] objectForKey:@”Restaurant_Name”] stringForKey:@”text”];

    Also, if you want to get rid of the leading and trailing whitespace, try this:

    restaurantName = [restaurantName stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

  7. Thanks Troy, but that leading and trailing white space not working for me:
    I have a string like this: myString =
    (
    “\n \n 24 K CLUB”,
    “\n \n 3 DOLLAR CAFE”,
    “\n \n A PEACH OF A PARTY”,
    “\n \n A ROYAL AFFAIR CAFE”,
    “\n \n AFFAIRS TO REMEMBER CATERERS”,
    “\n \n AFRIKAN DELI”)

    How to remove those new characters and white spaces

  8. You are just so nice to share this wonderful article. I have personally experienced in parsing around 20 xml files and I knew that what I did was a repeated job, have not thought of a solution in generic like yours. Cheers!!!

  9. Brilliant work, thank you so much!

  10. Thank you so much!

    If I may I would like to suggest not putting the “text” element in the dictionary, it’s one more value to navigate :P

    Great, really really great work!

  11. Please, put the code in github !!

  12. Nice piece of code, but wouldn’t it just make more sense to put values into arrays with 1 entry instead of NSDictionary and use NSDictionary only for attributes? I really hate to have to check what kind of object came back every time I am not sure about it…

    Alex

  13. Guys! Now you can fork and have fun ;)

    https://github.com/bcaccinolo/XML-to-NSDictionary

    Thanks for this great piece of code Troy !

  14. I don’t seem to be able to get this to work when passing an NSData object.. it returns ‘null’ to the console.

    NSDictionary *xmlDictionary = [XMLReader dictionaryForXMLData:responseData error:&parseError];

    Any ideas?

  15. I have wrote something just like yours but I am a fresh of obj-c, and my classes cause memory leaks, so thanks to your work, i will try it :p

  16. Thanks for posting this. I too had a “Ugh. Why isn’t this JSON?” moment tonight. I’m glad I found your snippet!

  17. @Abhi

    I was having the same issue as you, I’m trying something that might work but have yet to get to using the created dictionary object, i’ll let you know if i run into any issues (if i don’t reply again, obviously no issues)

    In the XMLReader.m file change the foundCharacters: function to — [textInProgress appendString:[string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]]; stripping out the whitespace and newline characters before it’s added to the dictonary item.

     

  18. Hi, this class was amazingly helpful. Thanks. I’ve made a couple of small changes that make it a bit easier to work with. In my situation, my xml doesn’t use attributes; rather the tag values are all there is. I’ve changed the class as follows:

    1. Added a public method:

    + (NSDictionary *)dictionaryForPath:(NSString *)path error:(NSError **)errorPointer;

    2. Got rid of some memory leaks that build&analyse spotted.

    3. When there are no attributes for a tag, but there is a “text” value, to replace the single entry dictionary with a simple string object containing the tag value. This makes it so much easier to get string tag values without having to negotiate dictionaries.

    I was going to replace the single item dictionaries with arrays for consistency, but decided it was actually handy to be able to use the iskindofclass() to quickly determine whether it would be an array or a single item dictionary.

    I’ve forked in the repository and delivered my changes.

  19. Thanks for posting this.Your generic method for solving the hectic problem of xml parsing was truly helpful.Now am having another problem..I am developing an application based on a survey,which includes matrix multiple choice questions for which i am not having any idea about implementing it.i am sure you will help me on this…waiting for your valuable response..Thanks in advance.. :-)

  20. this utility worked great. it converted my xml to a dictionary. now i want to break up the dictionary into separate arrays….or is it more common to break it up into sub dictionaries? essentially i want to take chunks of the dictionary so that i can create a grid of UIViews or UIImages.

    so this works fine for all the keys and values:
    for (id key in xmlDictionary) {
    NSLog(@”key: %@, value: %@”, key, [xmlDictionary objectForKey:key]);
    }
    here is a portion of the dictionary that i wrote to the console:
    section = (
    {
    name = running;
    pic = “main_running.jpg”;
    text = “\n\t\n\t\tmain running blah t”;
    },
    {
    name = “women’s training”;
    pic = “main_womentrain.jpg”;
    text = ” \n\t\tmain women train txt”;
    },

    as an example how do i create a array of the “pic” keys in this dictionary? from there i’m hoping i can create my grid of images.

    thanks for this utility. it works great and i think i’m close to figuring out how to manipulate a dictionary,
    josh

  21. Mate how do i get this reading a XML from the web?

  22. Hey,
    I tried your code and it works great however Im having problems displaying the data in a table view. It’s a little trickier to populate a TableView with a dictionary than an nsarray.
    Any pointers on that?

  23. Latest fork from github is providing a slightly nicer dictionary result for strings:
    https://github.com/Insert-Witty-Name/XML-to-NSDictionary

    Many improvements were done (memory leaks, strings, paths, …).

  24. iam a newbie in ios programming.I need your help.
    I have an XMl file which i parsed using NSXML parser but the issue iam facing is i cant store or access the attributes using NSMutableArray.
    can u help me in writing a code for the below XML for extracting the values and store in an NSMutable array. And also i have an issue in my parser that is my function [attributeDict objectForKey:key] is returning null.(i used the in place of key @”VehicleName”)

    demof

    OR 02AT-2110

    Stop

    NA

    0

    0 hrs 46 min 5sec

    Nandan Kanan Rd, Chandrasekharpur, Bhubaneswar, Orissa, India

    OR 02AT-2110

    9937291959

    2011/06/09 15:57:27

    20.349966,85.825363

    TN 18B-0865(TM 10)

    Stop

    NA

    0

    5 hrs 6 min 38sec

    State Highway 113, Thandalam, Tamil Nadu, India

    TN 18A-0865

    9677127842

    2011/06/09 15:58:42

    13.005752,80.0931

    TN 18A-7204 (BK)

    Stop

    NA

    0

    1 hrs 55 min 14sec

    State Highway 27, Tamil Nadu, India

    TN 18A-7204

    9677128001

    2011/06/09 15:58:50

    11.153144,79.063321

    This is my xml

    }

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

    if ([elementName isEqualToString:@"LoginResponse"]&& (currentElement == nil))
    {
    [window addSubview:rootController.view];
    [UIView commitAnimations];

    arrayList = [ [NSMutableArray alloc] initWithObjects:@”hello”,vehicleName,nil];
    }

    currentElement = elementName;
    //NSLog(@”%@”,[attributeDict objectForKey :@"LoginResponse"]);

    }

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

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

    if([currentElement isEqualToString :@"VehicleName"])
    {
    vehicleName = string;
    NSLog(@”%@”,vehicleName);
    }

    // NSLog(@”array values are %@”,[arrayList objectAtIndex:1]);

    }

    - (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {

    NSLog(@”parsing error……………………………………………..”);

    }

    - (void)connectionDidFinishLoading:(NSURLConnection *)theConnection
    {
    // do something with the data
    // receivedData is declared as a method instance elsewhere
    printf(“Succeeded! Received bytes of data…………………………….\n\n\n\n”);

    NSLog(@”%@”,completeData);
    NSString *responseString1 = [[NSString alloc] initWithData:completeData encoding:NSISOLatin1StringEncoding];
    NSLog(@”%@”,responseString1);
    NSLog(@”testing4………”);
    NSXMLParser *pXML = [[NSXMLParser alloc] initWithData: completeData];

    [pXML setDelegate:self];
    [pXML parse];

    // release the connection, and the data object
    //[connection release];
    //[receivedData release];

    this is a part of my code and also i got the xml from a webserver
    please email help

  25. Thanks for this awesome bit of code, but I do think I’ve found what I think is a bug: it incorrectly parses a “self-closing” tag, such as “”. This results in an NSDictionary entry that has this value:

    “yt:assignable” = {
    text = “\n \n “;
    };

    Shouldn’t it just be an empty string?

    (Yes, I have the code and can fix it myself, but I figured I should let others know what I found.)

    Thanks again!

  26. The downloaded files are commented “Copyright…All Rights Reserved”. Are there licensing terms you want us to adhere to in using this?

  27. - NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
    + NSXMLParser *parser = [[[NSXMLParser alloc] initWithData:data] autorelease];

    This is the best simple code I have ever been looking for.

  28. Great! I was up and running in minutes! The only add I did was to put the code into trim whitespace (you had it as a comment). For my data the whitespace was hideous.

    Inside “didEndElement:”

    // Get rid of leading + trailing whitespace
    [dictInProgress setObject:[textInProgress stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]] forKey:kXMLReaderTextNodeKey];

  29. Now this is great going from XML to NSDictionary, but how difficult would it to go from NSDictionary back to XML producing the same exact XML? I see that it only “reads” XML, but doesn’t “write” to XML.

  30. hello there i was wondering how should do error handling for example if the xml got an error.. the source of xml if fetch from http.. it returns a NSData.. how should i do this thanks in advance for any help :)

  31. How can I use XMLReader with ARC? I converted code with Xcode but it does not work. Please help !!!

  32. i want to parse a url through xml.how can it be done?

  33. Your style is really unique in comparison to other people I have read stuff from. I appreciate you for posting when you’ve got the opportunity, Guess I’ll just bookmark this page.

  34. Is there an updated version for ARC? Also, GitHub version would be great!

  35. I would really like to use this code in a commercial product I’m working on, but you have a copyright in the code files without a license agreement statement. My boss says we can’t use it without one, and we can’t use any of the GitHub offspring because the original you wrote has the copyright. Could you please post the license text with source zip, preferably the MIT license? I would also love to see the ARC version. Thanks for posting this code, I hope I’ll be able to work with it. Thanks.

  36. Hi,
    I’m a new to objective-c and I’m trying to process the data shown below. This is the result of processing a NOAA xml file using the XMLReader. I have spent days trying to process this data. If anyone might be able to give me some pointers it would be greatly appreciated. i would like to be able to pullout temperatures, weather forecasts, icons, etc.

    2012-12-22 20:28:53.591 Demo[6090:c07] Print the _xmlDictionary {
    dwml = {
    “@version” = “1.0″;
    “@xmlns:xsd” = “http://www.w3.org/2001/XMLSchema”;
    “@xmlns:xsi” = “http://www.w3.org/2001/XMLSchema-instance”;
    “@xsi:noNamespaceSchemaLocation” = “http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd”;
    data = (
    {
    “@type” = forecast;
    location = {
    city = {
    “@state” = WI;
    text = Kenosha;
    };
    description = “Kenosha, WI”;
    height = {
    “@datum” = “mean sea level”;
    text = 666;
    };
    “location-key” = point1;
    point = {
    “@latitude” = “42.58″;
    “@longitude” = “-87.86″;
    };
    };
    moreWeatherInformation = {
    “@applicable-location” = point1;
    text = “http://forecast.weather.gov/MapClick.php?lat=42.58&lon=-87.86″;
    };
    parameters = {
    “@applicable-location” = point1;
    “conditions-icon” = {
    “@time-layout” = “k-p12h-n14-1″;
    “@type” = “forecast-NWS”;
    “icon-link” = (
    “http://forecast.weather.gov/images/wtf/medium/nfew.png”,
    “http://forecast.weather.gov/images/wtf/medium/sct.png”,
    “http://forecast.weather.gov/images/wtf/medium/nbkn.png”,
    “http://forecast.weather.gov/images/wtf/medium/sn40.png”,
    “http://forecast.weather.gov/images/wtf/medium/nsn40.png”,
    “http://forecast.weather.gov/images/wtf/medium/sn40.png”,
    “http://forecast.weather.gov/images/wtf/medium/nsn40.png”,
    “http://forecast.weather.gov/images/wtf/medium/sn40.png”,
    “http://forecast.weather.gov/images/wtf/medium/nsn20.png”,
    “http://forecast.weather.gov/images/wtf/medium/bkn.png”,
    “http://forecast.weather.gov/images/wtf/medium/nbkn.png”,
    “http://forecast.weather.gov/images/wtf/medium/bkn.png”,
    “http://forecast.weather.gov/images/wtf/medium/nsn40.png”,
    “http://forecast.weather.gov/images/wtf/medium/sn40.png”
    );
    name = “Conditions Icon”;
    };
    “probability-of-precipitation” = {
    “@time-layout” = “k-p12h-n14-1″;
    “@type” = “12 hour”;
    “@units” = percent;
    name = “12 Hourly Probability of Precipitation”;
    value = (
    {
    “@xsi:nil” = true;
    },
    {
    “@xsi:nil” = true;
    },
    {
    “@xsi:nil” = true;
    },
    40,
    40,
    40,
    40,
    40,
    20,
    {
    “@xsi:nil” = true;
    },
    {
    “@xsi:nil” = true;
    },
    {
    “@xsi:nil” = true;
    },
    40,
    40
    );
    };
    temperature = (
    {
    “@time-layout” = “k-p24h-n7-1″;
    “@type” = minimum;
    “@units” = Fahrenheit;
    name = “Daily Minimum Temperature”;
    value = (
    18,
    27,
    23,
    21,
    17,
    18,
    24
    );
    },
    {
    “@time-layout” = “k-p24h-n7-2″;
    “@type” = maximum;
    “@units” = Fahrenheit;
    name = “Daily Maximum Temperature”;
    value = (
    32,
    32,
    30,
    29,
    27,
    30,
    31
    );
    }
    );
    weather = {
    “@time-layout” = “k-p12h-n14-1″;
    name = “Weather Type, Coverage, Intensity”;
    “weather-conditions” = (
    {
    “@weather-summary” = “Mostly Clear”;
    },
    {
    “@weather-summary” = “Mostly Sunny”;
    },
    {
    “@weather-summary” = “Chance Flurries”;
    },
    {
    “@weather-summary” = “Chance Snow”;
    },
    {
    “@weather-summary” = “Chance Snow”;
    },
    {
    “@weather-summary” = “Chance Snow”;
    },
    {
    “@weather-summary” = “Chance Snow”;
    },
    {
    “@weather-summary” = “Chance Snow”;
    },
    {
    “@weather-summary” = “Slight Chc Snow”;
    },
    {
    “@weather-summary” = “Partly Sunny”;
    },
    {
    “@weather-summary” = “Mostly Cloudy”;
    },
    {
    “@weather-summary” = “Mostly Cloudy”;
    },
    {
    “@weather-summary” = “Chance Snow”;
    },
    {
    “@weather-summary” = “Chance Snow”;
    }
    );
    };
    wordedForecast = {
    “@dataSource” = mkxNetcdf;
    “@time-layout” = “k-p12h-n14-1″;
    “@wordGenerator” = markMitchell;
    name = “Text Forecast”;
    text = (
    “Mostly clear, with a low around 18. Southwest wind 5 to 10 mph becoming northwest after midnight.”,
    “Mostly sunny, with a high near 32. North wind 5 to 10 mph.”,
    “Scattered flurries after midnight. Mostly cloudy, with a low around 27. East wind 5 to 10 mph.”,
    “A 40 percent chance of snow. Cloudy, with a high near 32. East wind around 10 mph becoming north in the afternoon.”,
    “A 40 percent chance of snow showers. Mostly cloudy, with a low around 23. North wind 5 to 10 mph.”,
    “A 40 percent chance of snow showers. Mostly cloudy, with a high near 30. North wind 5 to 10 mph.”,
    “A 40 percent chance of snow showers. Mostly cloudy, with a low around 21. North wind 10 to 15 mph.”,
    “A 40 percent chance of snow showers. Mostly cloudy, with a high near 29. North wind around 15 mph, with gusts as high as 25 mph.”,
    “A 20 percent chance of snow showers. Mostly cloudy, with a low around 17.”,
    “Partly sunny, with a high near 27.”,
    “Mostly cloudy, with a low around 18.”,
    “Mostly cloudy, with a high near 30.”,
    “A 40 percent chance of snow. Cloudy, with a low around 24.”,
    “A 40 percent chance of snow. Cloudy, with a high near 31.”
    );
    };
    };
    “time-layout” = (
    {
    “@summarization” = 12hourly;
    “@time-coordinate” = local;
    “layout-key” = “k-p12h-n14-1″;
    “start-valid-time” = (
    {
    “@period-name” = Tonight;
    text = “2012-12-22T18:00:00-06:00″;
    },
    {
    “@period-name” = Sunday;
    text = “2012-12-23T06:00:00-06:00″;
    },
    {
    “@period-name” = “Sunday Night”;
    text = “2012-12-23T18:00:00-06:00″;
    },
    {
    “@period-name” = Monday;
    text = “2012-12-24T06:00:00-06:00″;
    },
    {
    “@period-name” = “Monday Night”;
    text = “2012-12-24T18:00:00-06:00″;
    },
    {
    “@period-name” = “Christmas Day”;
    text = “2012-12-25T06:00:00-06:00″;
    },
    {
    “@period-name” = “Tuesday Night”;
    text = “2012-12-25T18:00:00-06:00″;
    },
    {
    “@period-name” = Wednesday;
    text = “2012-12-26T06:00:00-06:00″;
    },
    {
    “@period-name” = “Wednesday Night”;
    text = “2012-12-26T18:00:00-06:00″;
    },
    {
    “@period-name” = Thursday;
    text = “2012-12-27T06:00:00-06:00″;
    },
    {
    “@period-name” = “Thursday Night”;
    text = “2012-12-27T18:00:00-06:00″;
    },
    {
    “@period-name” = Friday;
    text = “2012-12-28T06:00:00-06:00″;
    },
    {
    “@period-name” = “Friday Night”;
    text = “2012-12-28T18:00:00-06:00″;
    },
    {
    “@period-name” = Saturday;
    text = “2012-12-29T06:00:00-06:00″;
    }
    );
    },
    {
    “@summarization” = 12hourly;
    “@time-coordinate” = local;
    “layout-key” = “k-p24h-n7-1″;
    “start-valid-time” = (
    {
    “@period-name” = Tonight;
    text = “2012-12-22T18:00:00-06:00″;
    },
    {
    “@period-name” = “Sunday Night”;
    text = “2012-12-23T18:00:00-06:00″;
    },
    {
    “@period-name” = “Monday Night”;
    text = “2012-12-24T18:00:00-06:00″;
    },
    {
    “@period-name” = “Tuesday Night”;
    text = “2012-12-25T18:00:00-06:00″;
    },
    {
    “@period-name” = “Wednesday Night”;
    text = “2012-12-26T18:00:00-06:00″;
    },
    {
    “@period-name” = “Thursday Night”;
    text = “2012-12-27T18:00:00-06:00″;
    },
    {
    “@period-name” = “Friday Night”;
    text = “2012-12-28T18:00:00-06:00″;
    }
    );
    },
    {
    “@summarization” = 12hourly;
    “@time-coordinate” = local;
    “layout-key” = “k-p24h-n7-2″;
    “start-valid-time” = (
    {
    “@period-name” = Sunday;
    text = “2012-12-23T06:00:00-06:00″;
    },
    {
    “@period-name” = Monday;
    text = “2012-12-24T06:00:00-06:00″;
    },
    {
    “@period-name” = “Christmas Day”;
    text = “2012-12-25T06:00:00-06:00″;
    },
    {
    “@period-name” = Wednesday;
    text = “2012-12-26T06:00:00-06:00″;
    },
    {
    “@period-name” = Thursday;
    text = “2012-12-27T06:00:00-06:00″;
    },
    {
    “@period-name” = Friday;
    text = “2012-12-28T06:00:00-06:00″;
    },
    {
    “@period-name” = Saturday;
    text = “2012-12-29T06:00:00-06:00″;
    }
    );
    }
    );
    },
    {
    “@type” = “current observations”;
    location = {
    “area-description” = “Kenosha Regional Airport, WI”;
    height = {
    “@datum” = “mean sea level”;
    “@height-units” = feet;
    text = 761;
    };
    “location-key” = point1;
    point = {
    “@latitude” = “42.59″;
    “@longitude” = “-87.94″;
    };
    };
    moreWeatherInformation = {
    “@applicable-location” = point1;
    text = “http://www.nws.noaa.gov/data/obhistory/KENW.html”;
    };
    parameters = {
    “@applicable-location” = point1;
    “conditions-icon” = {
    “@time-layout” = “k-p1h-n1-1″;
    “@type” = “forecast-NWS”;
    “icon-link” = “http://forecast.weather.gov/images/wtf/medium/nsct.png”;
    name = “Conditions Icon”;
    };
    direction = {
    “@time-layout” = “k-p1h-n1-1″;
    “@type” = wind;
    “@units” = “degrees true”;
    value = 160;
    };
    humidity = {
    “@time-layout” = “k-p1h-n1-1″;
    “@type” = relative;
    value = 78;
    };
    pressure = {
    “@time-layout” = “k-p1h-n1-1″;
    “@type” = barometer;
    “@units” = “inches of mercury”;
    value = “29.98″;
    };
    temperature = (
    {
    “@time-layout” = “k-p1h-n1-1″;
    “@type” = apparent;
    “@units” = Fahrenheit;
    value = 22;
    },
    {
    “@time-layout” = “k-p1h-n1-1″;
    “@type” = “dew point”;
    “@units” = Fahrenheit;
    value = 16;
    }
    );
    weather = {
    “@time-layout” = “k-p1h-n1-1″;
    name = “Weather Type, Coverage, Intensity”;
    “weather-conditions” = (
    {
    “@weather-summary” = Fair;
    },
    {
    value = {
    visibility = {
    “@units” = “statute miles”;
    text = “10.00″;
    };
    };
    }
    );
    };
    “wind-speed” = (
    {
    “@time-layout” = “k-p1h-n1-1″;
    “@type” = gust;
    “@units” = knots;
    value = NA;
    },
    {
    “@time-layout” = “k-p1h-n1-1″;
    “@type” = sustained;
    “@units” = knots;
    value = 3;
    }
    );
    };
    “time-layout” = {
    “@time-coordinate” = local;
    “layout-key” = “k-p1h-n1-1″;
    “start-valid-time” = {
    “@period-name” = current;
    text = “2012-12-22T19:53:00-06:00″;
    };
    };
    }
    );
    head = {
    product = {
    “@concise-name” = dwmlByDay;
    “@operational-mode” = developmental;
    “@srsName” = “WGS 1984″;
    category = “current observations and forecast”;
    “creation-date” = {
    “@refresh-frequency” = PT1H;
    text = “2012-12-22T19:36:29-06:00″;
    };
    };
    source = {
    credit = “http://www.crh.noaa.gov/mkx”;
    “more-information” = “http://www.nws.noaa.gov/forecasts/xml/”;
    “production-center” = “Milwaukee, WI”;
    };
    };
    };
    }
    2012-12-22 20:28:53.648 Demo[6090:c07] The key dwml
    2012-12-22 20:28:53.649 Demo[6090:c07] The value for the key {
    “@version” = “1.0″;
    “@xmlns:xsd” = “http://www.w3.org/2001/XMLSchema”;
    “@xmlns:xsi” = “http://www.w3.org/2001/XMLSchema-instance”;
    “@xsi:noNamespaceSchemaLocation” = “http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd”;
    data = (
    {
    “@type” = forecast;
    location = {
    city = {
    “@state” = WI;
    text = Kenosha;
    };
    description = “Kenosha, WI”;
    height = {
    “@datum” = “mean sea level”;
    text = 666;
    };
    “location-key” = point1;
    point = {
    “@latitude” = “42.58″;
    “@longitude” = “-87.86″;
    };
    };
    moreWeatherInformation = {
    “@applicable-location” = point1;
    text = “http://forecast.weather.gov/MapClick.php?lat=42.58&lon=-87.86″;
    };
    parameters = {
    “@applicable-location” = point1;
    “conditions-icon” = {
    “@time-layout” = “k-p12h-n14-1″;
    “@type” = “forecast-NWS”;
    “icon-link” = (
    “http://forecast.weather.gov/images/wtf/medium/nfew.png”,
    “http://forecast.weather.gov/images/wtf/medium/sct.png”,
    “http://forecast.weather.gov/images/wtf/medium/nbkn.png”,
    “http://forecast.weather.gov/images/wtf/medium/sn40.png”,
    “http://forecast.weather.gov/images/wtf/medium/nsn40.png”,
    “http://forecast.weather.gov/images/wtf/medium/sn40.png”,
    “http://forecast.weather.gov/images/wtf/medium/nsn40.png”,
    “http://forecast.weather.gov/images/wtf/medium/sn40.png”,
    “http://forecast.weather.gov/images/wtf/medium/nsn20.png”,
    “http://forecast.weather.gov/images/wtf/medium/bkn.png”,
    “http://forecast.weather.gov/images/wtf/medium/nbkn.png”,
    “http://forecast.weather.gov/images/wtf/medium/bkn.png”,
    “http://forecast.weather.gov/images/wtf/medium/nsn40.png”,
    “http://forecast.weather.gov/images/wtf/medium/sn40.png”
    );
    name = “Conditions Icon”;
    };
    “probability-of-precipitation” = {
    “@time-layout” = “k-p12h-n14-1″;
    “@type” = “12 hour”;
    “@units” = percent;
    name = “12 Hourly Probability of Precipitation”;
    value = (
    {
    “@xsi:nil” = true;
    },
    {
    “@xsi:nil” = true;
    },
    {
    “@xsi:nil” = true;
    },
    40,
    40,
    40,
    40,
    40,
    20,
    {
    “@xsi:nil” = true;
    },
    {
    “@xsi:nil” = true;
    },
    {
    “@xsi:nil” = true;
    },
    40,
    40
    );
    };
    temperature = (
    {
    “@time-layout” = “k-p24h-n7-1″;
    “@type” = minimum;
    “@units” = Fahrenheit;
    name = “Daily Minimum Temperature”;
    value = (
    18,
    27,
    23,
    21,
    17,
    18,
    24
    );
    },
    {
    “@time-layout” = “k-p24h-n7-2″;
    “@type” = maximum;
    “@units” = Fahrenheit;
    name = “Daily Maximum Temperature”;
    value = (
    32,
    32,
    30,
    29,
    27,
    30,
    31
    );
    }
    );
    weather = {
    “@time-layout” = “k-p12h-n14-1″;
    name = “Weather Type, Coverage, Intensity”;
    “weather-conditions” = (
    {
    “@weather-summary” = “Mostly Clear”;
    },
    {
    “@weather-summary” = “Mostly Sunny”;
    },
    {
    “@weather-summary” = “Chance Flurries”;
    },
    {
    “@weather-summary” = “Chance Snow”;
    },
    {
    “@weather-summary” = “Chance Snow”;
    },
    {
    “@weather-summary” = “Chance Snow”;
    },
    {
    “@weather-summary” = “Chance Snow”;
    },
    {
    “@weather-summary” = “Chance Snow”;
    },
    {
    “@weather-summary” = “Slight Chc Snow”;
    },
    {
    “@weather-summary” = “Partly Sunny”;
    },
    {
    “@weather-summary” = “Mostly Cloudy”;
    },
    {
    “@weather-summary” = “Mostly Cloudy”;
    },
    {
    “@weather-summary” = “Chance Snow”;
    },
    {
    “@weather-summary” = “Chance Snow”;
    }
    );
    };
    wordedForecast = {
    “@dataSource” = mkxNetcdf;
    “@time-layout” = “k-p12h-n14-1″;
    “@wordGenerator” = markMitchell;
    name = “Text Forecast”;
    text = (
    “Mostly clear, with a low around 18. Southwest wind 5 to 10 mph becoming northwest after midnight.”,
    “Mostly sunny, with a high near 32. North wind 5 to 10 mph.”,
    “Scattered flurries after midnight. Mostly cloudy, with a low around 27. East wind 5 to 10 mph.”,
    “A 40 percent chance of snow. Cloudy, with a high near 32. East wind around 10 mph becoming north in the afternoon.”,
    “A 40 percent chance of snow showers. Mostly cloudy, with a low around 23. North wind 5 to 10 mph.”,
    “A 40 percent chance of snow showers. Mostly cloudy, with a high near 30. North wind 5 to 10 mph.”,
    “A 40 percent chance of snow showers. Mostly cloudy, with a low around 21. North wind 10 to 15 mph.”,
    “A 40 percent chance of snow showers. Mostly cloudy, with a high near 29. North wind around 15 mph, with gusts as high as 25 mph.”,
    “A 20 percent chance of snow showers. Mostly cloudy, with a low around 17.”,
    “Partly sunny, with a high near 27.”,
    “Mostly cloudy, with a low around 18.”,
    “Mostly cloudy, with a high near 30.”,
    “A 40 percent chance of snow. Cloudy, with a low around 24.”,
    “A 40 percent chance of snow. Cloudy, with a high near 31.”
    );
    };
    };
    “time-layout” = (
    {
    “@summarization” = 12hourly;
    “@time-coordinate” = local;
    “layout-key” = “k-p12h-n14-1″;
    “start-valid-time” = (
    {
    “@period-name” = Tonight;
    text = “2012-12-22T18:00:00-06:00″;
    },
    {
    “@period-name” = Sunday;
    text = “2012-12-23T06:00:00-06:00″;
    },
    {
    “@period-name” = “Sunday Night”;
    text = “2012-12-23T18:00:00-06:00″;
    },
    {
    “@period-name” = Monday;
    text = “2012-12-24T06:00:00-06:00″;
    },
    {
    “@period-name” = “Monday Night”;
    text = “2012-12-24T18:00:00-06:00″;
    },
    {
    “@period-name” = “Christmas Day”;
    text = “2012-12-25T06:00:00-06:00″;
    },
    {
    “@period-name” = “Tuesday Night”;
    text = “2012-12-25T18:00:00-06:00″;
    },
    {
    “@period-name” = Wednesday;
    text = “2012-12-26T06:00:00-06:00″;
    },
    {
    “@period-name” = “Wednesday Night”;
    text = “2012-12-26T18:00:00-06:00″;
    },
    {
    “@period-name” = Thursday;
    text = “2012-12-27T06:00:00-06:00″;
    },
    {
    “@period-name” = “Thursday Night”;
    text = “2012-12-27T18:00:00-06:00″;
    },
    {
    “@period-name” = Friday;
    text = “2012-12-28T06:00:00-06:00″;
    },
    {
    “@period-name” = “Friday Night”;
    text = “2012-12-28T18:00:00-06:00″;
    },
    {
    “@period-name” = Saturday;
    text = “2012-12-29T06:00:00-06:00″;
    }
    );
    },
    {
    “@summarization” = 12hourly;
    “@time-coordinate” = local;
    “layout-key” = “k-p24h-n7-1″;
    “start-valid-time” = (
    {
    “@period-name” = Tonight;
    text = “2012-12-22T18:00:00-06:00″;
    },
    {
    “@period-name” = “Sunday Night”;
    text = “2012-12-23T18:00:00-06:00″;
    },
    {
    “@period-name” = “Monday Night”;
    text = “2012-12-24T18:00:00-06:00″;
    },
    {
    “@period-name” = “Tuesday Night”;
    text = “2012-12-25T18:00:00-06:00″;
    },
    {
    “@period-name” = “Wednesday Night”;
    text = “2012-12-26T18:00:00-06:00″;
    },
    {
    “@period-name” = “Thursday Night”;
    text = “2012-12-27T18:00:00-06:00″;
    },
    {
    “@period-name” = “Friday Night”;
    text = “2012-12-28T18:00:00-06:00″;
    }
    );
    },
    {
    “@summarization” = 12hourly;
    “@time-coordinate” = local;
    “layout-key” = “k-p24h-n7-2″;
    “start-valid-time” = (
    {
    “@period-name” = Sunday;
    text = “2012-12-23T06:00:00-06:00″;
    },
    {
    “@period-name” = Monday;
    text = “2012-12-24T06:00:00-06:00″;
    },
    {
    “@period-name” = “Christmas Day”;
    text = “2012-12-25T06:00:00-06:00″;
    },
    {
    “@period-name” = Wednesday;
    text = “2012-12-26T06:00:00-06:00″;
    },
    {
    “@period-name” = Thursday;
    text = “2012-12-27T06:00:00-06:00″;
    },
    {
    “@period-name” = Friday;
    text = “2012-12-28T06:00:00-06:00″;
    },
    {
    “@period-name” = Saturday;
    text = “2012-12-29T06:00:00-06:00″;
    }
    );
    }
    );
    },
    {
    “@type” = “current observations”;
    location = {
    “area-description” = “Kenosha Regional Airport, WI”;
    height = {
    “@datum” = “mean sea level”;
    “@height-units” = feet;
    text = 761;
    };
    “location-key” = point1;
    point = {
    “@latitude” = “42.59″;
    “@longitude” = “-87.94″;
    };
    };
    moreWeatherInformation = {
    “@applicable-location” = point1;
    text = “http://www.nws.noaa.gov/data/obhistory/KENW.html”;
    };
    parameters = {
    “@applicable-location” = point1;
    “conditions-icon” = {
    “@time-layout” = “k-p1h-n1-1″;
    “@type” = “forecast-NWS”;
    “icon-link” = “http://forecast.weather.gov/images/wtf/medium/nsct.png”;
    name = “Conditions Icon”;
    };
    direction = {
    “@time-layout” = “k-p1h-n1-1″;
    “@type” = wind;
    “@units” = “degrees true”;
    value = 160;
    };
    humidity = {
    “@time-layout” = “k-p1h-n1-1″;
    “@type” = relative;
    value = 78;
    };
    pressure = {
    “@time-layout” = “k-p1h-n1-1″;
    “@type” = barometer;
    “@units” = “inches of mercury”;
    value = “29.98″;
    };
    temperature = (
    {
    “@time-layout” = “k-p1h-n1-1″;
    “@type” = apparent;
    “@units” = Fahrenheit;
    value = 22;
    },
    {
    “@time-layout” = “k-p1h-n1-1″;
    “@type” = “dew point”;
    “@units” = Fahrenheit;
    value = 16;
    }
    );
    weather = {
    “@time-layout” = “k-p1h-n1-1″;
    name = “Weather Type, Coverage, Intensity”;
    “weather-conditions” = (
    {
    “@weather-summary” = Fair;
    },
    {
    value = {
    visibility = {
    “@units” = “statute miles”;
    text = “10.00″;
    };
    };
    }
    );
    };
    “wind-speed” = (
    {
    “@time-layout” = “k-p1h-n1-1″;
    “@type” = gust;
    “@units” = knots;
    value = NA;
    },
    {
    “@time-layout” = “k-p1h-n1-1″;
    “@type” = sustained;
    “@units” = knots;
    value = 3;
    }
    );
    };
    “time-layout” = {
    “@time-coordinate” = local;
    “layout-key” = “k-p1h-n1-1″;
    “start-valid-time” = {
    “@period-name” = current;
    text = “2012-12-22T19:53:00-06:00″;
    };
    };
    }
    );
    head = {
    product = {
    “@concise-name” = dwmlByDay;
    “@operational-mode” = developmental;
    “@srsName” = “WGS 1984″;
    category = “current observations and forecast”;
    “creation-date” = {
    “@refresh-frequency” = PT1H;
    text = “2012-12-22T19:36:29-06:00″;
    };
    };
    source = {
    credit = “http://www.crh.noaa.gov/mkx”;
    “more-information” = “http://www.nws.noaa.gov/forecasts/xml/”;
    “production-center” = “Milwaukee, WI”;
    };
    };
    }
    2012-12-22 20:28:53.672 Demo[6090:c07] subDictionary= {
    “@version” = “1.0″;
    “@xmlns:xsd” = “http://www.w3.org/2001/XMLSchema”;
    “@xmlns:xsi” = “http://www.w3.org/2001/XMLSchema-instance”;
    “@xsi:noNamespaceSchemaLocation” = “http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd”;
    data = (
    {
    “@type” = forecast;
    location = {
    city = {
    “@state” = WI;
    text = Kenosha;
    };
    description = “Kenosha, WI”;
    height = {
    “@datum” = “mean sea level”;
    text = 666;
    };
    “location-key” = point1;
    point = {
    “@latitude” = “42.58″;
    “@longitude” = “-87.86″;
    };
    };
    moreWeatherInformation = {
    “@applicable-location” = point1;
    text = “http://forecast.weather.gov/MapClick.php?lat=42.58&lon=-87.86″;
    };
    parameters = {
    “@applicable-location” = point1;
    “conditions-icon” = {
    “@time-layout” = “k-p12h-n14-1″;
    “@type” = “forecast-NWS”;
    “icon-link” = (
    “http://forecast.weather.gov/images/wtf/medium/nfew.png”,
    “http://forecast.weather.gov/images/wtf/medium/sct.png”,
    “http://forecast.weather.gov/images/wtf/medium/nbkn.png”,
    “http://forecast.weather.gov/images/wtf/medium/sn40.png”,
    “http://forecast.weather.gov/images/wtf/medium/nsn40.png”,
    “http://forecast.weather.gov/images/wtf/medium/sn40.png”,
    “http://forecast.weather.gov/images/wtf/medium/nsn40.png”,
    “http://forecast.weather.gov/images/wtf/medium/sn40.png”,
    “http://forecast.weather.gov/images/wtf/medium/nsn20.png”,
    “http://forecast.weather.gov/images/wtf/medium/bkn.png”,
    “http://forecast.weather.gov/images/wtf/medium/nbkn.png”,
    “http://forecast.weather.gov/images/wtf/medium/bkn.png”,
    “http://forecast.weather.gov/images/wtf/medium/nsn40.png”,
    “http://forecast.weather.gov/images/wtf/medium/sn40.png”
    );
    name = “Conditions Icon”;
    };
    “probability-of-precipitation” = {
    “@time-layout” = “k-p12h-n14-1″;
    “@type” = “12 hour”;
    “@units” = percent;
    name = “12 Hourly Probability of Precipitation”;
    value = (
    {
    “@xsi:nil” = true;
    },
    {
    “@xsi:nil” = true;
    },
    {
    “@xsi:nil” = true;
    },
    40,
    40,
    40,
    40,
    40,
    20,
    {
    “@xsi:nil” = true;
    },
    {
    “@xsi:nil” = true;
    },
    {
    “@xsi:nil” = true;
    },
    40,
    40
    );
    };
    temperature = (
    {
    “@time-layout” = “k-p24h-n7-1″;
    “@type” = minimum;
    “@units” = Fahrenheit;
    name = “Daily Minimum Temperature”;
    value = (
    18,
    27,
    23,
    21,
    17,
    18,
    24
    );
    },
    {
    “@time-layout” = “k-p24h-n7-2″;
    “@type” = maximum;
    “@units” = Fahrenheit;
    name = “Daily Maximum Temperature”;
    value = (
    32,
    32,
    30,
    29,
    27,
    30,
    31
    );
    }
    );
    weather = {
    “@time-layout” = “k-p12h-n14-1″;
    name = “Weather Type, Coverage, Intensity”;
    “weather-conditions” = (
    {
    “@weather-summary” = “Mostly Clear”;
    },
    {
    “@weather-summary” = “Mostly Sunny”;
    },
    {
    “@weather-summary” = “Chance Flurries”;
    },
    {
    “@weather-summary” = “Chance Snow”;
    },
    {
    “@weather-summary” = “Chance Snow”;
    },
    {
    “@weather-summary” = “Chance Snow”;
    },
    {
    “@weather-summary” = “Chance Snow”;
    },
    {
    “@weather-summary” = “Chance Snow”;
    },
    {
    “@weather-summary” = “Slight Chc Snow”;
    },
    {
    “@weather-summary” = “Partly Sunny”;
    },
    {
    “@weather-summary” = “Mostly Cloudy”;
    },
    {
    “@weather-summary” = “Mostly Cloudy”;
    },
    {
    “@weather-summary” = “Chance Snow”;
    },
    {
    “@weather-summary” = “Chance Snow”;
    }
    );
    };
    wordedForecast = {
    “@dataSource” = mkxNetcdf;
    “@time-layout” = “k-p12h-n14-1″;
    “@wordGenerator” = markMitchell;
    name = “Text Forecast”;
    text = (
    “Mostly clear, with a low around 18. Southwest wind 5 to 10 mph becoming northwest after midnight.”,
    “Mostly sunny, with a high near 32. North wind 5 to 10 mph.”,
    “Scattered flurries after midnight. Mostly cloudy, with a low around 27. East wind 5 to 10 mph.”,
    “A 40 percent chance of snow. Cloudy, with a high near 32. East wind around 10 mph becoming north in the afternoon.”,
    “A 40 percent chance of snow showers. Mostly cloudy, with a low around 23. North wind 5 to 10 mph.”,
    “A 40 percent chance of snow showers. Mostly cloudy, with a high near 30. North wind 5 to 10 mph.”,
    “A 40 percent chance of snow showers. Mostly cloudy, with a low around 21. North wind 10 to 15 mph.”,
    “A 40 percent chance of snow showers. Mostly cloudy, with a high near 29. North wind around 15 mph, with gusts as high as 25 mph.”,
    “A 20 percent chance of snow showers. Mostly cloudy, with a low around 17.”,
    “Partly sunny, with a high near 27.”,
    “Mostly cloudy, with a low around 18.”,
    “Mostly cloudy, with a high near 30.”,
    “A 40 percent chance of snow. Cloudy, with a low around 24.”,
    “A 40 percent chance of snow. Cloudy, with a high near 31.”
    );
    };
    };
    “time-layout” = (
    {
    “@summarization” = 12hourly;
    “@time-coordinate” = local;
    “layout-key” = “k-p12h-n14-1″;
    “start-valid-time” = (
    {
    “@period-name” = Tonight;
    text = “2012-12-22T18:00:00-06:00″;
    },
    {
    “@period-name” = Sunday;
    text = “2012-12-23T06:00:00-06:00″;
    },
    {
    “@period-name” = “Sunday Night”;
    text = “2012-12-23T18:00:00-06:00″;
    },
    {
    “@period-name” = Monday;
    text = “2012-12-24T06:00:00-06:00″;
    },
    {
    “@period-name” = “Monday Night”;
    text = “2012-12-24T18:00:00-06:00″;
    },
    {
    “@period-name” = “Christmas Day”;
    text = “2012-12-25T06:00:00-06:00″;
    },
    {
    “@period-name” = “Tuesday Night”;
    text = “2012-12-25T18:00:00-06:00″;
    },
    {
    “@period-name” = Wednesday;
    text = “2012-12-26T06:00:00-06:00″;
    },
    {
    “@period-name” = “Wednesday Night”;
    text = “2012-12-26T18:00:00-06:00″;
    },
    {
    “@period-name” = Thursday;
    text = “2012-12-27T06:00:00-06:00″;
    },
    {
    “@period-name” = “Thursday Night”;
    text = “2012-12-27T18:00:00-06:00″;
    },
    {
    “@period-name” = Friday;
    text = “2012-12-28T06:00:00-06:00″;
    },
    {
    “@period-name” = “Friday Night”;
    text = “2012-12-28T18:00:00-06:00″;
    },
    {
    “@period-name” = Saturday;
    text = “2012-12-29T06:00:00-06:00″;
    }
    );
    },
    {
    “@summarization” = 12hourly;
    “@time-coordinate” = local;
    “layout-key” = “k-p24h-n7-1″;
    “start-valid-time” = (
    {
    “@period-name” = Tonight;
    text = “2012-12-22T18:00:00-06:00″;
    },
    {
    “@period-name” = “Sunday Night”;
    text = “2012-12-23T18:00:00-06:00″;
    },
    {
    “@period-name” = “Monday Night”;
    text = “2012-12-24T18:00:00-06:00″;
    },
    {
    “@period-name” = “Tuesday Night”;
    text = “2012-12-25T18:00:00-06:00″;
    },
    {
    “@period-name” = “Wednesday Night”;
    text = “2012-12-26T18:00:00-06:00″;
    },
    {
    “@period-name” = “Thursday Night”;
    text = “2012-12-27T18:00:00-06:00″;
    },
    {
    “@period-name” = “Friday Night”;
    text = “2012-12-28T18:00:00-06:00″;
    }
    );
    },
    {
    “@summarization” = 12hourly;
    “@time-coordinate” = local;
    “layout-key” = “k-p24h-n7-2″;
    “start-valid-time” = (
    {
    “@period-name” = Sunday;
    text = “2012-12-23T06:00:00-06:00″;
    },
    {
    “@period-name” = Monday;
    text = “2012-12-24T06:00:00-06:00″;
    },
    {
    “@period-name” = “Christmas Day”;
    text = “2012-12-25T06:00:00-06:00″;
    },
    {
    “@period-name” = Wednesday;
    text = “2012-12-26T06:00:00-06:00″;
    },
    {
    “@period-name” = Thursday;
    text = “2012-12-27T06:00:00-06:00″;
    },
    {
    “@period-name” = Friday;
    text = “2012-12-28T06:00:00-06:00″;
    },
    {
    “@period-name” = Saturday;
    text = “2012-12-29T06:00:00-06:00″;
    }
    );
    }
    );
    },
    {
    “@type” = “current observations”;
    location = {
    “area-description” = “Kenosha Regional Airport, WI”;
    height = {
    “@datum” = “mean sea level”;
    “@height-units” = feet;
    text = 761;
    };
    “location-key” = point1;
    point = {
    “@latitude” = “42.59″;
    “@longitude” = “-87.94″;
    };
    };
    moreWeatherInformation = {
    “@applicable-location” = point1;
    text = “http://www.nws.noaa.gov/data/obhistory/KENW.html”;
    };
    parameters = {
    “@applicable-location” = point1;
    “conditions-icon” = {
    “@time-layout” = “k-p1h-n1-1″;
    “@type” = “forecast-NWS”;
    “icon-link” = “http://forecast.weather.gov/images/wtf/medium/nsct.png”;
    name = “Conditions Icon”;
    };
    direction = {
    “@time-layout” = “k-p1h-n1-1″;
    “@type” = wind;
    “@units” = “degrees true”;
    value = 160;
    };
    humidity = {
    “@time-layout” = “k-p1h-n1-1″;
    “@type” = relative;
    value = 78;
    };
    pressure = {
    “@time-layout” = “k-p1h-n1-1″;
    “@type” = barometer;
    “@units” = “inches of mercury”;
    value = “29.98″;
    };
    temperature = (
    {
    “@time-layout” = “k-p1h-n1-1″;
    “@type” = apparent;
    “@units” = Fahrenheit;
    value = 22;
    },
    {
    “@time-layout” = “k-p1h-n1-1″;
    “@type” = “dew point”;
    “@units” = Fahrenheit;
    value = 16;
    }
    );
    weather = {
    “@time-layout” = “k-p1h-n1-1″;
    name = “Weather Type, Coverage, Intensity”;
    “weather-conditions” = (
    {
    “@weather-summary” = Fair;
    },
    {
    value = {
    visibility = {
    “@units” = “statute miles”;
    text = “10.00″;
    };
    };
    }
    );
    };
    “wind-speed” = (
    {
    “@time-layout” = “k-p1h-n1-1″;
    “@type” = gust;
    “@units” = knots;
    value = NA;
    },
    {
    “@time-layout” = “k-p1h-n1-1″;
    “@type” = sustained;
    “@units” = knots;
    value = 3;
    }
    );
    };
    “time-layout” = {
    “@time-coordinate” = local;
    “layout-key” = “k-p1h-n1-1″;
    “start-valid-time” = {
    “@period-name” = current;
    text = “2012-12-22T19:53:00-06:00″;
    };
    };
    }
    );
    head = {
    product = {
    “@concise-name” = dwmlByDay;
    “@operational-mode” = developmental;
    “@srsName” = “WGS 1984″;
    category = “current observations and forecast”;
    “creation-date” = {
    “@refresh-frequency” = PT1H;
    text = “2012-12-22T19:36:29-06:00″;
    };
    };
    source = {
    credit = “http://www.crh.noaa.gov/mkx”;
    “more-information” = “http://www.nws.noaa.gov/forecasts/xml/”;
    “production-center” = “Milwaukee, WI”;
    };
    };
    }

  37. HI Jim, I spent days scrolling down here.

  38. Since not clear how to extract particular items from ur example.

    For example,
    1. If I wanted to extract all the ‘Text’ inside ‘topping’?
    2. If I wanted to access the value of ‘name’?

    I tried as the example above but it throws an error.
    NSString *nameStr = [[[[[xmlDictionary objectForKey:@"items"] objectForKey:@”item”] objectForKey:@”batters”] objectForKey:@”batter”] stringForKey:@”name”];

    Any help?

  39. Jim, you’re an idiot.

  40. As the liquid windows inside the front must prevent overfilling, I have to acknowledge which one sleepy day we was
    not having to pay attention and also forgot which I had already filled it
    along with liquid the event prior to. Drip Coffee Maker Commonly Asked Questions Precisely what exactly is definitely the ideal heat for brewing coffee?
    Many specialists consent which 200 degrees is among the most effective temperature for brewing coffee.

  41. Choose avantage d’avantage de tous seuls vous amène vraiment un la mode, le style, ULTRAVIOLET la protection toutefois en plus le la part de légende comme de your life, alors . dans chaque le cas right maintenant vous are a averti de ce particulier offre, le partager à your très propre famille et aussi les amis, elle will est les branches d’heureux.
    cannot de might de légende de mode sent a créé every l’an d’an .
    every un des l’Interdiction de Ray Les lunettes de soleil bon marché are as longtemps comme avec un le certificat d’authenticité qui contient le code.
    . COULEUR multinationale les cadres, les branches ou a teinté des lunettes, les combinaisons a tendance à être innombrable et la
    collection continue à augmenter chaque saison l’été d’été.

  42. The use of abrasive toothpaste is in essence the destructive process as it carefully rubs away at the
    glass surface to help make the abrasion the exact
    same levels because the surrounding exterior. Even when your eating room is actually little and
    also simple, you are able to write a glamorous place that is practical and also inviting.
    rather of maintaining a perfect granite top dining table, you may find
    the glass cut as part of a great inverted arc shape during the corners.
    This can be the hard pad over the entire table or
    a sweet tablecloth these as one found at Bed, Bath and also Beyond.

  43. Alike activities tend to be carried out for introducing products among
    some other sections of the society, too.
    There are lots of methods to generate leads, exclusive the few
    of what kind of have been covered below. These charts definitely will give your networking plans and also the actions
    your men and women definitely will take to improve any credibility with the
    powerful and also important. The most excellent program for your
    is dependent on the nature of your very own business and also the lifestyles of
    your prospect leads.

  44. It will consist of just what you will most likely wear,
    the atmosphere which you choose and also different things that are required in order
    to go with during the session. nowadays, naturally,
    as soon as as part of awhile you will definitely get no reply or perhaps have refusals, however
    that is all role of the this particular path. It definitely will teach
    you about the right shutter speeds in order to capture stills and also movements.
    Most theater providers and also venues have danger zones, guides of conduct and etiquette.
    If your have the expertise, right equipment, and permit in order to
    work, free up a little space in your very own home and
    turn it inside the mini salon.

  45. A home and every thing in it can also become stylish .
    Beautify your home by adding several Ralph Lauren beddings and
    decorations. Those who wish to beautify their homes with
    simple and modernly designed furnishings with good quality ought to choose the Lauren home collections.
    They created their home collections with the same level of inspired style that they put into their
    clothing line.

  46. Jim, go kill yourself please.

Leave a Reply