6

我了解了当前的 NSXMLParser。我阅读了许多教程,但没有人能准确地告诉我它是如何工作的。有关于 StackOverflow 的教程吗?我的问题是我的应用程序中的这个 KML 读取结构并使用 MKMapView 显示

我的 Parser 类看起来像:

#import <Foundation/Foundation.h>

@interface Parser : NSXMLParser

@property (nonatomic, strong) NSString *rowElementName; // this is the element name that identifies a new row of data in the XML
@property (nonatomic, strong) NSArray *attributeNames;  // this is the array of attributes we might want to retrieve for that element name
@property (nonatomic, strong) NSArray *elementNames;    // this is the list of sub element names for which we're retrieving values

@property (nonatomic, strong) NSMutableArray *items;    // after parsing, this is the array of parsed items

@end

#import "Parser.h"

@interface Parser () <NSXMLParserDelegate>

@property (nonatomic, strong) NSMutableDictionary *item;     // while parsing, this is the item currently being parsed
@property (nonatomic, strong) NSMutableString *elementValue; // this is the element within that item being parsed

@end

@implementation Parser

- (id)initWithContentsOfURL:(NSURL *)url
{
    self = [super initWithContentsOfURL:url];

    if (self)
    {
        self.delegate = self;
    }

    return self;
}

- (id)initWithData:(NSData *)data
{
    self = [super initWithData:data];

    if (self)
    {
        self.delegate = self;
    }

    return self;
}

- (id)initWithStream:(NSInputStream *)stream
{
    self = [super initWithStream:stream];

    if (self)
    {
        self.delegate = self;
    }

    return self;
}

#pragma mark - NSXMLParserDelegate methods

- (void)parserDidStartDocument:(NSXMLParser *)parser
{
    self.items = [[NSMutableArray alloc] init];

    if (!self.rowElementName)
        NSLog(@"%s Warning: Failed to specify row identifier element name", __FUNCTION__);
}

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict
{
    if ([elementName isEqualToString:self.rowElementName])
    {
        self.item  = [[NSMutableDictionary alloc] init];

        for (NSString *attributeName in self.attributeNames)
        {
            id attributeValue = [attributeDict valueForKey:attributeName];
            if (attributeValue)
                [self.item setObject:attributeValue forKey:attributeName];
        }
    }
    else if ([self.elementNames containsObject:elementName])
    {
        self.elementValue = [[NSMutableString alloc] init];
    }
}

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

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
    if ([elementName isEqualToString:self.rowElementName])
    {
        [self.items addObject:self.item];
        self.item = nil;
    }
    else if ([self.elementNames containsObject:elementName])
    {
        [self.item setValue:self.elementValue forKey:elementName];
        self.elementValue = nil;
    }
}

@end

rob创建

我的 XML 文件:

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.1">
<Document>
    <name>Filename.kml</name>
    <Style id="style1">
        <IconStyle>
            <Icon>
                <href>http://imageshack.us/a/img825/9079/pinvi.png</href>
            </Icon>
        </IconStyle>
    </Style>
    <Placemark>
        <name><![CDATA[Blankenese]]></name>
        <Snippet><![CDATA[Blankeneser Bahnhofstr. 9 22587 Hamburg +49-(0)40-866 06 50 +49-(0)40-86 60 65 60]]></Snippet>
        <description><![CDATA[<img src="http://www.engelvoelkers.com/shops/de-blankenese-res.jpg"><br/>Blankeneser Bahnhofstr. 9<br/>22587 Hamburg<br/>Telefon: +49-(0)40-866 06 50<br/>Fax: +49-(0)40-86 60 65 60<br/><a href="http://www.engelvoelkers.com/elbe">Website</a><br/>E-Mail: Blankenese@engelvoelkers.com]]></description>
        <styleUrl>#style1</styleUrl>
        <Point>
            <coordinates>9.811470,53.559441</coordinates>
        </Point>
    </Placemark>
</Document>
</kml>

我的目标是获取<description>标签中的所有信息并像谷歌地图一样显示它在此处输入图像描述

不完全是类似的。

但首先我需要知道如何使用解析器

最好的问候 CTS

4

2 回答 2

16

这个问题有两个根本不同的组成部分,解析和注释地图。我将在这里关注地图注释,因为我想我在这里讨论了解析问题:尝试在 MKMapView 中加载创建的地图。不过,在这个答案的最后,我会引用一些苹果的解析文档,如果你只是想把你的手臂放在身边的话NSXMLParser

注释地图

iPhone 上地图应用程序的常见模式是不在地图视图本身上显示内容丰富的弹出框,而是由于 iPhone 的有限空间,仅显示标准标注,但将 设置rightCalloutAccessoryView为披露指示器,如果您点击它,它将转到下一个视图的详细信息。因此,通过使用UIMapViewDelegate方法,你可以有一个mapView:viewForAnnotation:说:

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
    MKAnnotationView *annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"loc"];
    annotationView.canShowCallout = YES;
    annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];

    return annotationView;
}

这将产生以下用户界面:

右侧标注附件

然后你可以有一个mapView:annotationView:calloutAccessoryControlTapped:这样的:

- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
    [self performSegueWithIdentifier:@"DetailsIphone" sender:view];
}

您可以使用它转到您的详细信息屏幕。(我只是对带有 web 视图的视图控制器进行模态搜索prepareForSegueviewDidLoad在设计比这个快速而肮脏的 Web 视图更漂亮的东西……我只是在演示我们可以从 KML 文件中获取地标的 HTML):

iPhone 详细信息屏幕

因此,虽然 iPhone 确实不应该在地图本身上使用弹出框,但在 iPad 上,您可以使用它们。您可以rightCalloutAccessoryView以类似的方式创建(尽管可能使用“信息”按钮而不是详细信息披露):

iPad 右侧标注配件

但是在这里,您mapView:annotationView:calloutAccessoryControlTapped:实际上可以生成弹出框,而不是进行模态转换:

- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
    //CGRect frame = view.frame;
    [mapView deselectAnnotation:view.annotation animated:YES];
    
    DetailsViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:@"DetailsPopover"];
    controller.annotation = view.annotation;
    self.popover = [[UIPopoverController alloc] initWithContentViewController:controller];
    self.popover.delegate = self;
    [self.popover presentPopoverFromRect:view.frame
                                  inView:view.superview
                permittedArrowDirections:UIPopoverArrowDirectionAny
                                animated:YES];
}

产生:

iPad弹出框

顺便说一句,这大致近似于 iPad 地图应用程序的操作方式(当您单击图钉时,它会向您显示带有“信息”按钮的标注),如果您随后单击信息按钮,则会显示弹出框有细节。

或者,您可以单击图钉将您带到弹出窗口,绕过干预标注。不过,为此,您首先必须禁用注释视图本身的标注:

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
    MKAnnotationView *annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"loc"];
    annotationView.canShowCallout = NO;

    return annotationView;
}

但是你必须回应mapView:didSelectAnnotationView:

- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
    [mapView deselectAnnotation:view.annotation animated:YES];

    DetailsViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:@"DetailsPopover"];
    controller.annotation = view.annotation;
    self.popover = [[UIPopoverController alloc] initWithContentViewController:controller];
    self.popover.delegate = self;
    [self.popover presentPopoverFromRect:view.frame
                                  inView:view.superview
                permittedArrowDirections:UIPopoverArrowDirectionAny
                                animated:YES];
}

理论上,你可以在 iPhone 上做这样的事情,但由于你不能使用UIPopoverController,你必须使用一些第三方弹出框(或自己编写)。我听说有些人声称苹果拒绝 iPhone 应用程序使用弹出视图,但我既不能证实这一点,也不能说这是否是一个硬性规定。我只知道 Apple 和 Google iPhone 地图应用程序不会在 iPhone 地图应用程序上使用大的弹出视图(Apple 转向另一个视图,谷歌让它出现在屏幕底部)。如果您考虑一下,如果图钉正好在中心,并且您试图生成一个指向该图钉的大弹出框,它可能会变得狭窄。

无论如何,这些是使用rightCalloutAccessoryView设置和/或直接禁用canShowCallout和显示弹出框的选项。


解析参考:

地图视图标注参考:

于 2013-01-31T05:53:37.910 回答
1

解析器是这样工作的,打开根标签,然后搜索子标签。当没有更多嵌套标签时,将读取数据,在这里您可以选择如何保存数据。还有许多其他可用的解析器。通过 gDataXMLParser。我已经使用它并且工作得很好,如果有嵌套标签,请确保递归调用解析器。如果您正在寻找特定标签,请使用字符串查找子字符串,即;从<b></b>类似的内容并读取其中的文本。

于 2013-01-30T16:27:43.660 回答