将XML转换为Dictionary时,防止创建额外的对象

时间:2012-07-30 23:58:14

标签: iphone objective-c ios cocoa

使用XML阅读器将XML String转换为数组。解析器正在将一个子元素添加到键“value”中,而我的obj-c技能还不足以弄清楚如何防止它 - 我是一个PHP人并帮助了一个朋友。我还需要关闭2个子元素,以便办公室和办公室出现。

我输入什么

        <?xml version="1.0" encoding="utf-8"?>
        <offices>
          <office>
            <phone>02-7532490</phone>
            <address>312 Sen. Gil Puyat Avenue, 18th Flr. Trident Tower</address>
            <suburb>Makati</suburb>
            <postcode>1200</postcode>
            <email>careers@drakepersonnel.com.ph</email>
            <name>Drake Makati</name>
            <latitude>14.56213</latitude>
            <longitude>121.02437</longitude>
          </office>
        </offices>

我从解析器中得到什么

            {
                offices =     {
                    office =         {
                        Address =             {
                            value = "312 Sen. Gil Puyat Avenue, 18th Flr. Trident Tower";
                        };
                        Emails =             {
                            value = "careers@drakepersonnel.com.ph";
                        };
                        Office =             {
                            value = Makati;
                        };
                        Tel =             {
                            value = "02-7532490";
                        };
                        latitude =             {
                            value = "14.56213";
                        };
                        longitude =             {
                            value = "121.02437";
                        };
                        name =             {
                            value = "Drake Makati";
                        };
                        postcode =             {
                            value = 1200;
                        };
                        value = "";
                    };
                    value = "";
                };
            }

我想从解析器得到什么(有些标签不一样......我知道)

            (
                    {
                    Address = "1904B 19th Floor West Tower, Philippine Stock Exchange Centre, Exchange Road, Ortigas Center, Pasig City 1600";
                    Emails = "clients@drakepersonnel.com.ph";
                    Fax = "632 753 1524 loc 106";
                    GeoLocation = "14.58273, 121.06154";
                    Office = Philippines;
                    Tel = "632 753 1522-24 / 632 753 2490-93";
                }
            )

这是使用

的XMLreader.m文件
        //
        //  XMLReader.m
        //
        //  Created by Troy on 9/18/10.
        //  Updated by Antoine Marcadet on 9/23/11.
        //

        #import "XMLReader.h"

        NSString *const kXMLReaderTextNodeKey       = @"value";
        NSString *const kXMLReaderAttributePrefix   = @"@";

        @interface XMLReader ()

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

        @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 options:0];
            [reader release];
            return rootDictionary;
        }

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

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

        + (NSDictionary *)dictionaryForXMLString:(NSString *)string options:(XMLReaderOptions)options error:(NSError **)error
        {
            NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
            return [XMLReader dictionaryForXMLData:data options:options 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 options:(XMLReaderOptions)options
        {
            // 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 setShouldProcessNamespaces:(options & XMLReaderOptionsProcessNamespaces)];
            [parser setShouldReportNamespacePrefixes:(options & XMLReaderOptionsReportNamespacePrefixes)];
            [parser setShouldResolveExternalEntities:(options & XMLReaderOptionsResolveExternalEntities)];

            parser.delegate = self;
            BOOL success = [parser parse];

            [parser release];

            // 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)
            {
                // trim after concatenating
                NSString *trimmedString = [textInProgress stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

                [dictInProgress setObject:[[trimmedString mutableCopy] autorelease] 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

任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

只需从XML解析器的结果字典中选择所需的值,问题在哪里?如果您知道XML元素名称,则可以轻松执行以下操作:

NSDictionary *xmlParsedDict = ....
NSDictionary *offices = [xmlParsedDict objectForKey:@"offices"];
NSDictionary *office = [offices objectForKey:@"office"];

此外,我希望XML元素offices可以包含多个办公室,因此您只需从office数组中收集所有offices字典。

干杯, ANKA