0

我尝试解析以下 XML 文件:

<MesPar DH="HBCHa" StrNr="2416" Typ="10" Var="10">
    <Name>Aabach - Hitzkirch</Name>
    <Datum>11.11.2013</Datum>
    <Zeit>18:00</Zeit>
    <Wert>2.02</Wert>
    <Wert dt="-24h">1.93</Wert>
</MesPar>

<MesPar DH="HBCHa" StrNr="2312" Typ="02" Var="00">
    <Name>Aach - Salmsach</Name>
    <Datum>11.11.2013</Datum>
    <Zeit>18:00</Zeit>
    <Wert>406.47</Wert>
    <Wert dt="-24h">406.64</Wert>
</MesPar>

如果属性“StrNr”等于“2416”,我将读取元素值。我的代码是:

NSURL *url = [NSURL URLWithString:@"http://www.hydrodaten.admin.ch/lhg/SMS.xml"];
NSData *webData = [NSData dataWithContentsOfURL:url options:NSUTF8StringEncoding error:nil];
TFHpple *parser = [TFHpple hppleWithData:webData isXML:YES];
NSString *xPathQuery = @"//AKT_Data/MesPar";
NSArray *arrayPaser= [parser searchWithXPathQuery:xPathQuery];

NSMutableArray *arrayName = [[NSMutableArray alloc] initWithCapacity:0];
NSMutableArray *arrayDatum = [[NSMutableArray alloc] initWithCapacity:0];
NSMutableArray *arrayWertDt24h = [[NSMutableArray alloc] initWithCapacity:0];


for (TFHppleElement *element in arrayPaser) {
    if ([[element firstChild] content]!=nil) {
        NSDictionary *attribute=[element attributes];

        NSString *string= [NSString stringWithFormat:@"%@",[attribute valueForKey:@"StrNr"]];

        if ([string isEqualToString:@"2416"]) {

            arrayName addObject:[element ??????];
            arrayDatum addObject:[element ?????];
            arrayWertDt24h addObject:[element ????];
        }

我不知道如何从元素中获取值?

4

1 回答 1

1

我有一个涉及使用内置 NSXMLParser 和几个 NSXMLParserDelegate 方法的解决方案。

让我们首先继承 NSObject 并创建一个解析器类。这是.h:

#import <Foundation/Foundation.h>

@interface XMLParser : NSObject

- (id)initWithData:(NSData *)data;
- (BOOL)parse;

@end

在这里您可以看到我们将向该对象提供您想要解析的数据,然后我们可以告诉它进行解析。parse 方法只是您稍后将看到的 NSXMLParser parse 方法的包装器。

类扩展是我们将在其中添加用于管理我们正在解析的数据的私有属性的地方。如下所示:

@interface XMLParser ()
<NSXMLParserDelegate>

@property (nonatomic, strong) NSData *data;
@property (nonatomic, strong) NSXMLParser *parser;
@property (nonatomic, strong) NSMutableDictionary *objectDict;
@property (nonatomic, strong) NSMutableString *elementDataString;
@property (nonatomic, strong) NSMutableDictionary *wertTwo;
@property (nonatomic, assign, getter = isParsingWertTwo) BOOL parsingWertTwo;

@end

和属性是不言自明的dataparser我们将使用该objectDict属性来存储您希望从此 XML 解析的数据。elementDataString 将保存解析器在元素标记之间找到的字符。我们有一个wertTwo属性和一个标志来指示我们何时解析第二个 Wert 元素。这样我们就可以确保从第二个 Wert 元素中获取属性。

实现的开头如下所示:

@implementation XMLParser

- (id)initWithData:(NSData *)data
{
    self = [super init];
    if (self) {
        self.data = data;
        self.parser = [[NSXMLParser alloc] initWithData:data];
        self.parser.delegate = self;
        self.objectDict = [@{} mutableCopy];
        self.wertTwo = [@{} mutableCopy];
    }
    return self;
}

- (BOOL)parse
{
    return [self.parser parse];
}

正如您从初始化程序中看到的那样,我们设置了我们需要的对象以及数据和解析器来进行实际的解析。我提到的 parse 方法只是简单地包装了 NSXMLParser 类的 parse 方法。它实际上返回一个 BOOL ,这也是我选择在这里返回它的原因。我们设置self为解析器的委托,因此我们必须实现委托协议中的一些方法才能获得必要的数据。委托方法如下所示:

#pragma mark - NSXMLParserDelegate

- (void)parser:(NSXMLParser *)parser
didStartElement:(NSString *)elementName
  namespaceURI:(NSString *)namespaceURI
 qualifiedName:(NSString *)qName
    attributes:(NSDictionary *)attributeDict
{
    if ([elementName isEqualToString:@"MesPar"]) {

        // Get the value from the attribute dict of the MesPar element
        NSString *value = attributeDict[@"StrNr"];

        // Compare whether the value is equal to the desired value
        if ([value isEqualToString:@"2416"]) {

            // if the value is equal, add the attribute dict to the object dict
            [self.objectDict addEntriesFromDictionary:attributeDict];

            return;
        }
    }

    // If the element is Wert AND there is an attribute named dt we know this is the second Wert element
    if ([elementName isEqualToString:@"Wert"] && attributeDict[@"dt"]) {

        // add the attribute element to the wertTwo dict
        [self.wertTwo addEntriesFromDictionary:attributeDict];

        // Set the parsing flag to YES so we know where we are in the delegate methods
        self.parsingWertTwo = YES;

        return;
    }
}

- (void)parser:(NSXMLParser *)parser
 didEndElement:(NSString *)elementName
  namespaceURI:(NSString *)namespaceURI
 qualifiedName:(NSString *)qName
{
    // if this is the Name element, set the element data in the object dict
    if ([elementName isEqualToString:@"Name"]) {
        [self.objectDict setObject:[self.elementDataString copy] forKey:@"name"];

        // set the data to nil since it will be reset by a delegate method for the next element
        self.elementDataString = nil;

        return;
    }

    if ([elementName isEqualToString:@"Datum"]) {
        [self.objectDict setObject:[self.elementDataString copy] forKey:@"datum"];

        // set the data to nil since it will be reset by a delegate method for the next element
        self.elementDataString = nil;

        return;
    }

    if ([elementName isEqualToString:@"Zeit"]) {
        [self.objectDict setObject:[self.elementDataString copy] forKey:@"zeit"];

        // set the data to nil since it will be reset by a delegate method for the next element
        self.elementDataString = nil;

        return;
    }


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

        // Checks to see if this is the Wert element AND that we are parsing the second element
        if (self.isParsingWertTwo) {
            [self.wertTwo setObject:[self.elementDataString copy] forKey:@"wertTwoString"];

            // set the wertTwo dict for the key wertTwo in the object dict
            // this allows us to pull out this info for the key wertTwo and includes the attribute of dt along with the elementDataString
            [self.objectDict setObject:[self.wertTwo copy] forKey:@"wertTwo"];

            // set the data to nil since it will be reset by a delegate method for the next element
            self.elementDataString = nil;

            return;
        }
        else{
            [self.objectDict setObject:[self.elementDataString copy] forKey:@"wertOne"];

            // set the data to nil since it will be reset by a delegate method for the next element
            self.elementDataString = nil;

            return;
        }
    }
}

- (void)parserDidEndDocument:(NSXMLParser *)parser
{
    // You do not have to implement this but if you'd like here you can access `self.objectDict` which should have a representation of your XML you're looking to parse
}


- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    // Append the foundCharacters (in between the element tags) to the data string
    [self.elementDataString appendString:string];
}

代码对实际发生的情况进行了注释,但简而言之,解析器正在通知委托,self在这种情况下,当某些事情发生时,例如遇到元素或查找字符时。要记住的一件事是该elementDataString属性需要延迟加载,我们这样做:

// lazy loads the elementDataString if it is nil
// it will be set to nil after each time it is set in a dict
// this is why we copy it when we add it to the dict
- (NSMutableString *)elementDataString
{
    if (!_elementDataString) {
        _elementDataString = [NSMutableString string];
    }
    return _elementDataString;
}

有几件事我没有解决,例如解析中的错误或您可能感兴趣的其他委托方法。这是一种特殊的解决方案,它利用内置类而不是依赖于第 3 方库。

于 2013-11-26T02:34:04.980 回答