0

我有一些由以下结构组成的 xml

<Succession SuccessionID= ....>
    <LinkedSuccession>
        <Succession SuccessionID= ..../> // multiple possible
    </LinkedSuccession>
    <SUF>
        <SeeAlsoSuccession>
            <Succession SuccessionID= ..../> // multiple possible
        </SeeAlsoSuccession>
    </SUF>
    <Plugins>
        <Plugin PluginIdent= ..../> // multiple possible
    </Plugins>
    <Card>
        <Actives>  // multiple possible
            <Active activeNo= ....>  // multiple possible
                <Machs>
                    <Mach Mach= ...../>  // multiple possible
                </Machs>
            </Active>
        </Actives>
    </Card>
</Succession>

我想知道如何使用 NSXMLParser 来解析这个我知道这两种方法

- (void)startTheParsingProcess:(NSData *)parserData
{
    NSXMLParser *parser = [[NSXMLParser alloc] initWithData:parserData]; //parserData passed to NSXMLParser delegate which starts the parsing process
    [parser setDelegate:self];
    [parser parse]; // starts the event-driven parsing operation.
}


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

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

    //..??


}

- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
{
    NSLog(@"Paser Error = %@", parseError);
    UIAlertView *errorAlert = [[UIAlertView alloc] initWithTitle:@"Error!" message:@"A parsing failure occurred." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
    [errorAlert show];
}


- (void)parserDidEndDocument:(NSXMLParser *)parser
{
 //..
}

通常我会使用这样的东西来访问每个元素,但是由于这个 xml 文件的结构,这个 dosnt 可以正常工作,就像它读取 Succession 时一样,如果只是用最后一个读取的值覆盖任何值。

if ([elementName isEqualToString:@"Succession"]) {

等等,但是这个 XML 文件的结构对我来说太多了。我希望得到一些关于如何使用 NSXMLParser 读取这个 xml 文件的帮助。

任何帮助将不胜感激。

4

4 回答 4

0

你如何处理这个 XML 将在很大程度上取决于你的数据模型有多健壮。如果您开始使用一些 NSMutableDictionaries 来提交您的数据,特别是那些您可能拥有同一元素的多个实例的数据,并与自定义数据类捆绑在一起,我认为您会做得更好。不使用重复数据的关键是利用 didEndElement 作为触发器将该元素提交到您的父数据类中,然后再生成另一个具有相同名称的元素。

于 2013-06-14T04:44:24.740 回答
0

您需要记住,实际上有两种方法可以使用 NSXMLParser 搜索 构建数据结构

如果您事先知道要处理的结构或模式,这些都不是那么糟糕。如果你不知道,那就是更多的工作,但是解析器为你提供了两个重要的方法 lineNumber 和 columnNumber

您可以利用这些优势。基本上,在处理未知 XML 结构时可以采用的策略是进行试运行或预解析。在那里,跟踪每列或元素或评论等的总列和行数,可能需要一些试验和错误才能习惯。但基本上你探究了 XML 的结构,然后你对后续轮次可以使用什么有了一些想法。

预解析的一个优点是它可以非常快。它还使后续的解析操作更容易和更快。

当您不知道您收到的确切内容并且它不小时,陷阱试图在一个解析操作中完成所有操作。

于 2013-06-14T09:25:33.107 回答
0

简单的解决方案是简单地拥有一些类属性来跟踪您是否在 aLinkedSuccession或 aSeeAlsoSuccession中,这样,当您遇到一个Succession元素时,您就会知道您是否在这两个子元素数组之一中,或者您是否正在处理顶级Succession条目,并采取相应的行动。


虽然有一些简单的方法可以解决您的问题,但如上所述,我可能会建议另外两种可能的NSXMLParser实现方式来帮助您应对挑战。第一个是NSXMLParser GitHub 上可用的基于块的实现。要将它与您的 XML 示例一起使用(其中您的所有数据似乎都在 XML 标记的属性中,您只需提供 a beginElementBlock,但在我提供的示例代码中,我还说明了您如何提供 a endElementBlock,也)。无论如何,使用您的示例 XML,您可以执行以下操作:

XMLBlockParser *parser = [[XMLBlockParser alloc] initWithData:data];

// handler for the parsing of the start of an element, often useful for parsing the attributes included within
// that opening element tag

parser.beginElementBlock = ^(NSArray *elementNames, NSDictionary *attributeDict) {
    NSString *elementName = [elementNames lastObject];

    if ([elementName isEqualToString:@"Succession"])
    {
        if ([elementNames count] == 1)
        {
            // top level "Succession": create an object

            self.currentObject = [NSMutableDictionary dictionary];
            [self.currentObject setObject:attributeDict[@"SuccessionID"] forKey:@"SuccessionID"];
            [self.objects addObject:self.currentObject];
        }
        else
        {
            // "Succession" in either "LinkedSuccession" or "SeeAlsoSuccession"

            // let's find the array "LinkedSuccession" or "SeeAlsoSuccession" objects

            NSString *container = elementNames[[elementNames count] - 2];
            NSMutableArray *array = self.currentObject[container];
            if (!array)
            {
                // if not found, then let's create it and add it to our currentObject

                array = [NSMutableArray array];
                self.currentObject[container] = array;
            }

            // how add the attributeDict value

            [array addObject:attributeDict[@"SuccessionID"]];
        }
    }
};

[parser parse];

另一种方法是使用一个NSXMLParser简单地将整个 XML 解析为一些嵌套树结构的方法,例如GitHub 上的这个示例。为此,您不必编写任何特定于应用程序的代码来解析 XML,但您最终也会得到比标准NSArray/更复杂的东西NSDictionary

您有许多可能的方法。我希望这有帮助。

于 2013-06-14T04:37:25.903 回答
0

这是一些可能有帮助的伪代码:

NSMutableArray *linkedSuccessionIDs = [NSMutableArray array];
NSMutableArray *seeAlsoSuccessionIDs = [NSMutableArray array];
BOOL isInLinkedSuccession = NO;
BOOL isInSeeAlsoSuccession = NO;

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
    if ([elementName isEqualToString:@"LinkedSuccession"])
    {
        isInLinkedSuccession = YES;
    }
    else if ([elementName isEqualToString:@"SeeAlsoSuccession"])
    {
        isInSeeAlsoSuccession = YES;
    }
    else if ([elementName isEqualToString:@"Succession"])
    {
        if (isInLinkedSuccession)
        {
            [linkedSuccessionIDs addObject:[attributeDict[@"SuccessionID"]]];
        }
        else if (isInSeeAlsoSuccession)
        {
            [seeAlsoSuccessionIDs addObject:[attributeDict[@"SuccessionID"]]];
        }
    }
}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
    if ([elementName isEqualToString:@"LinkedSuccession"])
    {
        isInLinkedSuccession = NO;
    }
    else if ([elementName isEqualToString:@"SeeAlsoSuccession"])
    {
        isInSeeAlsoSuccession = NO;
    }
}

- (void)parserDidEndDocument:(NSXMLParser *)parser
{
    [self processLinkedSuccessionIDs:linkedSuccessionIDs];
    [self processSeeAlsoSuccessionIDs:seeAlsoSuccessionIDs];
}
于 2013-06-14T15:16:50.133 回答