【问题标题】:iOS NSXMLParser Value with Category ie. <Product category="ABC"> in tableviews带有类别的 iOS NSXMLParser 值,即。表格视图中的 <Product category="ABC">
【发布时间】:2012-12-02 17:19:03
【问题描述】:

我有一个 XML,它将代表一个产品目录,其中每个产品都属于一个类别。即:

<Product category="ABC">
 <Item_number>123</Item_number>
</Product>

<Product category="ABC">
 <Item_number>456</Item_number>
</Product>

<Product category="XYZ">
 <Item_number>789</Item_number>
</Product>

我创建了一个类来存储数据,然后将一个实例放入一个数组中。* 然后将它显示到一个 tableview 上。目前,tableview 显示一个 Item_numbers 列表:D

我想要实现的是相同的,但我希望有 2 页。具有非重复(唯一)类别(即 ABC、XYZ)的主表视图,在第二页 - 详细表视图上,它将显示属于所选类别的 item_number。像这样..

主表视图:

ABC >
XYZ >

详细表格视图(选择“ABC”):

123
456

(1) 最好的方法是什么?

(2) 我想我的第一个障碍是从“ABC”类别中解析出值

    <Product category="ABC">

在我的实现中,当我简单地调用时,我得到了空白(当 XML 中有一个类别时以某种方式解析一个值有点不同)

cell.textLabel.text = product.product;

(3) 第二个是我如何存储数据(或者我可以保持相同的方法*),其中详细的 Tableview 页面可以由用户从第一页选择单个类别来引用。


didStartElement 的当前实现

- (void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
        if ( [elementName isEqualToString:@"Product"] ){
            self.currentProduct = [[Product alloc] init];
            self.storeCharacters = NO;
        } else  if ([elementName isEqualToString:@"Item_Number"]) {
            [self.currentString setString:@""];
            self.storeCharacters = YES;
        }
    }

【问题讨论】:

  • 对不起 - 被剥夺了。我现在修复了 Q#2。谢谢

标签: ios xml xml-parsing tableview xcode4.5


【解决方案1】:

关于解析category,当elementName@"Product" 时,从attributes 字典中检索到didStartElement

就“最佳方法”而言,您只需要决定您的数据结构。我可能会建议构建一个 NSMutableArray,它是一个类别字典条目数组,每个类别一个,字典中的一个对象将是该类别中的一个产品数组。

一旦你有了这个结构,回答你的第三个问题可能就很明显了。


好的,首先,您的 XML 确实需要一个外部标记,例如:

<Products>
    <Product category="ABC">
        <Item_number>123</Item_number>
        <Description>Coffee table</Description>
    </Product>

    <Product category="ABC">
        <Item_number>456</Item_number>
        <Description>Lamp shade</Description>
    </Product>

    <Product category="XYZ">
        <Item_number>789</Item_number>
        <Description>Orange chair</Description>
    </Product>
</Products>

其次,假设您想要一个类别数组,并且对于每个类别,您想要一个产品数组,实现可能如下所示。首先,您需要一些属性,一个用于最终结果,另外两个用于解析期间使用的临时变量:

// this is our final result, an array of dictionaries for each categor

@property (nonatomic, strong) NSMutableArray *categories;

//  these are just temporary variables used during the parsing

@property (nonatomic, strong) NSMutableString *parserElementValue;
@property (nonatomic, strong) NSMutableDictionary *parserProduct;

然后NSXMLParserDelegate 方法可能看起来像:

#pragma mark - NSXMLParser delegate methods

- (void)parserDidStartDocument:(NSXMLParser *)parser
{
    self.categories = [NSMutableArray array];
}

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
    NSArray *subElementNames = @[@"Item_number", @"Description"];

    if ([elementName isEqualToString:@"Product"])
    {
        // get the name of the category attribute

        NSString *categoryName = [attributeDict objectForKey:@"category"];
        NSAssert(categoryName, @"no category found");

        // search our array of dictionaries of cateogries to see if we have one with a name equal to categoryName

        __block NSMutableDictionary *parserCurrentCategory = nil;
        [self.categories enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
            if ([categoryName isEqualToString:[obj objectForKey:@"name"]])
            {
                parserCurrentCategory = obj;
                *stop = YES;
            }
        }];

        // if we didn't find one, let's create one and add it to our array of cateogires

        if (!parserCurrentCategory)
        {
            parserCurrentCategory = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                    categoryName, @"name",
                                    [NSMutableArray array], @"items",
                                    nil];
            [self.categories addObject:parserCurrentCategory];
        }

        // Now let's add an entry to the items array for the product being added

        self.parserProduct = [NSMutableDictionary dictionary];
        [[parserCurrentCategory objectForKey:@"items"] addObject:self.parserProduct];
    }
    else if ([subElementNames containsObject:elementName])
    {
        self.parserElementValue = [NSMutableString string];
        [self.parserProduct setObject:self.parserElementValue forKey:elementName];
    }
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    if (self.parserElementValue)
        [self.parserElementValue appendString:string];
}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
    if ([elementName isEqualToString:@"Product"])
    {
        self.parserProduct = nil;
    }
    else if (self.parserElementValue)
    {
        self.parserElementValue = nil;
    }
}

- (void)parserDidEndDocument:(NSXMLParser *)parser
{
    // all done, do whatever you want, just as reloadData for your table

    NSLog(@"%s categories = %@", __FUNCTION__, self.categories);
}

- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
{
    NSLog(@"%s error=%@", __FUNCTION__, parseError);
}

【讨论】:

  • 刚刚在我的帖子中粘贴了我的 didStartELement。像那样?如果是这样,我目前正在为产品获得空白:(
  • @Tim_User1904669 显然,您已经包含了didStartElement,但没有显示foundCharacters,产品ID 将在哪里构造,didEndElement 产品ID 将保存在哪里,所以我不可能说。但请参阅我更新的答案以了解另一种方法。
  • 天哪,你太棒了!它就像一个魅力!感谢您的所有努力。我可以从日志中看到它已经为每个类别分解了项目。现在是超级有趣的部分……将它们放入 tableviews 中。我可以只用类别来做主要的,但细节的可能是一个挑战。我去看看能不能找到一些教程。再次感谢!你太棒了!
  • 不好意思问了。如果我在 Product 中除了 Item_Number 之外还有更多元素怎么办?我是否需要创建另一个临时变量(即 NSMutableString *parserCurrentProductName)它在 NSXMLParserDelegate 方法中会是什么样子?
  • 谢谢!奇迹般有效。只是为了让我了解你的设计,这样我才能真正学习和消化。您创建了一个可变的类别数组,并且在其中,您有一个项目数组......并且对于每个项目,都有各种子元素构成一个单独的项目。我在正确的轨道上吗?我以前从未使用过字典,除了在一个教程中,我在 plist 中创建了字典并从中读取。 ~对不起,我是新手。 Objective C 对我来说(显然)是新的。我曾经用 Java 编写代码:D
猜你喜欢
  • 1970-01-01
  • 2012-03-28
  • 1970-01-01
  • 2015-02-10
  • 1970-01-01
  • 1970-01-01
  • 2012-10-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多