3

私はiOS開発の新人で、現時点では NSXMLparser を実装していますが、同じ名前でコンテンツが異なるタグを分離する方法が本当にわかりません<description>. 一部のフィードでは、このタグには概要のみが含まれており、他のフィードでは「 img src 」も含まれています。これも抽出したいと考えています。(CDATA の有無にかかわらず)

Example of description tags wich i need to grab the images and then pass to my UIImageView:

<description><![CDATA[ <p>Roger Craig Smith and Troy Baker to play Batman and the Joker respectively in upcoming action game; Deathstroke confirmed as playable character. </p><p><img src="http://image.com.com/gamespot/images/2013/139/ArkhamOrigins_29971_thumb.jpg"

<description>&lt;img src=&quot;http://cdn.gsmarena.com/vv/newsimg/13/05/samsung-galaxy-s4-active-photos/thumb.jpg&quot; width=&quot;70&quot; height=&quot;92&quot; hspace=&quot;3&quot; alt=&quot;&quot; border=&quot;0&quot; align=left style="background:#333333;padding:0px;margin:0px 4px 0px 0px;border-style:solid;border-color:#aaaaaa;border-width:1px" /&gt; &lt;p&gt;

@Rob ので問題は解決すると思いますが、データと画像を分離するために、以下で説明する NSXMLParser に含める方法がわかりません。このパーサーでは、データ (要約) のみを取得できます。

私の NSXMLParser:

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict
{
element = [elementName copy];


if ([elementName isEqualToString:@"item"])
{
    elements = [[NSMutableDictionary alloc] init];
    title = [[NSMutableString alloc] init];
    date = [[NSMutableString alloc] init];
    summary = [[NSMutableString alloc] init];
    link = [[NSMutableString alloc] init];
    img = [[NSMutableString alloc] init];
    imageLink = [[NSMutableString alloc]init];

}

if([elementName isEqualToString:@"media:thumbnail"]) {
    NSLog(@"thumbnails media:thumbnail: %@", attributeDict);
    imageLink = [attributeDict objectForKey:@"url"];
}

if([elementName isEqualToString:@"media:content"]) {
    NSLog(@"thumbnails media:content: %@", attributeDict);
    imageLink = [attributeDict objectForKey:@"url"];

}

if([elementName isEqualToString:@"enclosure"]) {
    NSLog(@"thumbnails Enclosure %@", attributeDict);
    imageLink = [attributeDict objectForKey:@"url"];
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if ([element isEqualToString:@"title"])
{
    [title appendString:string];
}
else if ([element isEqualToString:@"pubDate"])
{
    [date appendString:string];
}
else if ([element isEqualToString:@"description"])
{
    [summary appendString:string];

}
   else if ([element isEqualToString:@"media:description"])
{
    [summary appendString:string];

}
else if ([element isEqualToString:@"link"])
{
    [link appendString:string];
}
else if ([element isEqualToString:@"url"]) {

    [imageLink appendString:string];
}
else if ([element isEqualToString:@"src"]) {

    [imageLink appendString:string];
}
else if ([element isEqualToString:@"content:encoded"]){
    NSString *imgString = [self getImage:string];
    if (imgString != nil) {
        [img appendString:imgString];
        NSLog(@"Content of img:%@", img);
    }

}

-(NSString *) getImage:(NSString *)htmlString {
NSString *url = nil;

NSScanner *theScanner = [NSScanner scannerWithString:htmlString];

[theScanner scanUpToString:@"<img" intoString:nil];
if (![theScanner isAtEnd]) {
    [theScanner scanUpToString:@"src" intoString:nil];
    NSCharacterSet *charset = [NSCharacterSet characterSetWithCharactersInString:@"\"'"];
    [theScanner scanUpToCharactersFromSet:charset intoString:nil];
    [theScanner scanCharactersFromSet:charset intoString:nil];
    [theScanner scanUpToCharactersFromSet:charset intoString:&url];

}
return url;
}

@end
4

1 に答える 1

2

あなたの例では、2 つのdescription要素しかなく、それぞれにimgタグが埋め込まれています。通常のようなものを解析しdescriptionてから、タグを引き出しimgます (正規表現を使用するか、retrieveImageSourceTagsViaRegex以下の my を使用するか、スキャナーを使用します)。

CDATA必要がない場合は、レンディションと非レンディションを別の方法で処理するCDATA必要はありません。ルーチンをNSXMLParserDelegate提供しますが、実際にはそれを実装しないfoundCDATA傾向があります。が存在しない場合、 の標準ルーチンは、タグの両方のレンディション( を使用する場合と使用しない場合) をシームレスに適切に処理します。foundCDATAfoundCharactersNSXMLParserdescriptionCDATA

次の架空の XML を考えてみましょう。

<xml>
    <descriptions>
        <description><![CDATA[ <p>Roger Craig Smith and Troy Baker to play Batman and the Joker respectively in upcoming action game; Deathstroke confirmed as playable character. </p><p><img src="http://image.com.com/gamespot/images/2013/139/ArkhamOrigins_29971_thumb.jpg">]]></description>
        <description>&lt;img src=&quot;http://cdn.gsmarena.com/vv/newsimg/13/05/samsung-galaxy-s4-active-photos/thumb.jpg&quot; width=&quot;70&quot; height=&quot;92&quot; hspace=&quot;3&quot; alt=&quot;&quot; border=&quot;0&quot; align=left style="background:#333333;padding:0px;margin:0px 4px 0px 0px;border-style:solid;border-color:#aaaaaa;border-width:1px" /&gt; &lt;p&gt;</description>
    </descriptions>
</xml>

description次のパーサーは、これらのエントリの両方を解析し、それらから画像の URL を取得します。CDATAご覧のとおり、neededには特別な処理はありません。

@interface ViewController () <NSXMLParserDelegate>

@property (nonatomic, strong) NSMutableString *description;
@property (nonatomic, strong) NSMutableArray *results;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    NSURL *filename = [[NSBundle mainBundle] URLForResource:@"test" withExtension:@"xml"];
    NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:filename];
    parser.delegate = self;
    [parser parse];

    // full array of dictionary entries

    NSLog(@"results = %@", self.results);
}

- (NSMutableArray *)retrieveImageSourceTagsViaRegex:(NSString *)string
{
    NSError *error = NULL;
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"(<img\\s[\\s\\S]*?src\\s*?=\\s*?['\"](.*?)['\"][\\s\\S]*?>)+?"
                                                                           options:NSRegularExpressionCaseInsensitive
                                                                             error:&error];

    NSMutableArray *results = [NSMutableArray array];

    [regex enumerateMatchesInString:string
                            options:0
                              range:NSMakeRange(0, [string length])
                         usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {

                             [results addObject:[string substringWithRange:[result rangeAtIndex:2]]];
                         }];

    return results;
}

#pragma mark - NSXMLParserDelegate

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

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
    if ([elementName isEqualToString:@"description"])
        self.description = [NSMutableString string];
}

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

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
    if ([elementName isEqualToString:@"description"])
    {
        NSArray *imgTags = [self retrieveImageSourceTagsViaRegex:self.description];
        NSDictionary *result = @{@"description": self.description, @"imgs" : imgTags};
        [self.results addObject:result];
        self.description = nil;
    }
}

@end

これにより、次の結果が得られます (注、 no CDATA)。

results = (
        {
        description = " <p>Roger Craig Smith and Troy Baker to play Batman and the Joker respectively in upcoming action game; Deathstroke confirmed as playable character. </p><p><img src=\"http://image.com.com/gamespot/images/2013/139/ArkhamOrigins_29971_thumb.jpg\">";
        imgs =         (
            "http://image.com.com/gamespot/images/2013/139/ArkhamOrigins_29971_thumb.jpg"
        );
    },
        {
        description = "<img src=\"http://cdn.gsmarena.com/vv/newsimg/13/05/samsung-galaxy-s4-active-photos/thumb.jpg\" width=\"70\" height=\"92\" hspace=\"3\" alt=\"\" border=\"0\" align=left style=\"background:#333333;padding:0px;margin:0px 4px 0px 0px;border-style:solid;border-color:#aaaaaa;border-width:1px\" /> <p>";
        imgs =         (
            "http://cdn.gsmarena.com/vv/newsimg/13/05/samsung-galaxy-s4-active-photos/thumb.jpg"
        );
    }
)

要するに、XML を通常のようにCDATA解析するだけNSScannerですNSRegularExpression

于 2013-05-21T00:12:22.920 に答える