iPhone上XML解析出现问题

3
当我从Web服务接收数据时,我的NSMutableData中填充了以下XML:
<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><GetWeatherResponse xmlns="http://www.webserviceX.NET"><GetWeatherResult>&lt;?xml version="1.0" encoding="utf-16"?&gt;
&lt;CurrentWeather&gt;
  &lt;Location&gt;BERLIN MUNICIPAL AIRPORT, NH, United States (KBML) 44-35N 71-11W 345M&lt;/Location&gt;
  &lt;Time&gt;Oct 19, 2010 - 03:52 AM EDT / 2010.10.19 0752 UTC&lt;/Time&gt;
  &lt;Wind&gt; Calm:0&lt;/Wind&gt;
  &lt;Visibility&gt; 10 mile(s):0&lt;/Visibility&gt;
  &lt;SkyConditions&gt; clear&lt;/SkyConditions&gt;
  &lt;Temperature&gt; 23.0 F (-5.0 C)&lt;/Temperature&gt;
  &lt;DewPoint&gt; 21.0 F (-6.1 C)&lt;/DewPoint&gt;
  &lt;RelativeHumidity&gt; 91&lt;/RelativeHumidity&gt;
  &lt;Pressure&gt; 29.83 in. Hg (1010 hPa)&lt;/Pressure&gt;
  &lt;Status&gt;Success&lt;/Status&gt;
&lt;/CurrentWeather&gt;</GetWeatherResult></GetWeatherResponse></soap:Body></soap:Envelope>

当我搜索“CurrentWeather”时,解析器无法找到它,因为存在&qt、&lt等字符。如何修复我的NSMutableData以具有正常的值(<,>等)?

完整代码:

#import "DemoWebServiceConsumeViewController.h"

@implementation DemoWebServiceConsumeViewController

@synthesize cityName;
@synthesize activityIndicator;
@synthesize location;

- (IBAction) hideKeyboard{
    [cityName resignFirstResponder];
}

- (IBAction) buttonClicked: (id)sender{

    [cityName resignFirstResponder];    

    NSString *soapMsg = 
    [NSString stringWithFormat:
     @"<?xml version=\"1.0\" encoding=\"utf-8\"?>"
     "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"
     "<soap:Body>"
     "<GetWeather xmlns=\"http://www.webserviceX.NET\">"
     "<CityName>%@</CityName>"
     "<CountryName>%@</CountryName>"
     "</GetWeather>"
     "</soap:Body>"
     "</soap:Envelope>", cityName.text, @"united states"
     ];

    NSLog(soapMsg);    

    NSURL *url = [NSURL URLWithString: 
                  @"http://www.webservicex.com/globalweather.asmx"];
    NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];

    //---set the headers---
    // here copy method name to be called SOAP Action read from WS description
    NSString *msgLength = [NSString stringWithFormat:@"%d", [soapMsg length]];
    [req addValue:@"text/xml; charset=utf-8" 
    forHTTPHeaderField:@"Content-Type"];
    [req addValue:@"http://www.webserviceX.NET/GetWeather" 
    forHTTPHeaderField:@"SOAPAction"];
    [req addValue:msgLength forHTTPHeaderField:@"Content-Length"];

    //---set the HTTP method and body---
    [req setHTTPMethod:@"POST"];
    [req setHTTPBody: [soapMsg dataUsingEncoding:NSUTF8StringEncoding]];


    [activityIndicator startAnimating];    

    conn = [[NSURLConnection alloc] initWithRequest:req delegate:self];
    if (conn) {
        webData = [[NSMutableData data] retain];
    }  
}

-(void) connection:(NSURLConnection *) connection 
didReceiveResponse:(NSURLResponse *) response {
    [webData setLength: 0];
}

-(void) connection:(NSURLConnection *) connection 
    didReceiveData:(NSData *) data {
    [webData appendData:data];
}

-(void) connection:(NSURLConnection *) connection 
  didFailWithError:(NSError *) error {
    [webData release];    
    [connection release];
}

-(void) connectionDidFinishLoading:(NSURLConnection *) connection {
    NSLog(@"DONE READING WEATHER WEB SERVICE. Received Bytes: %d", [webData length]);
    NSString *theXML = [[NSString alloc] 
                        initWithBytes: [webData mutableBytes] 
                        length:[webData length] 
                        encoding:NSUTF8StringEncoding];
    //---shows the XML---
    NSLog(theXML);  

    [theXML release]; 

    [activityIndicator stopAnimating];    

    if (xmlParser)
    {
        [xmlParser release];
    }
    xmlParser = [[NSXMLParser alloc] initWithData: webData];
                [xmlParser setDelegate:self];   
                [xmlParser setShouldResolveExternalEntities:YES];
                [xmlParser parse];


    [connection release];
    [webData release];
}

//---when the start of an element is found---
-(void) parser:(NSXMLParser *) parser 
    didStartElement:(NSString *) elementName 
    namespaceURI:(NSString *) namespaceURI 
    qualifiedName:(NSString *) qName
    attributes:(NSDictionary *) attributeDict {


    NSLog(elementName);
    if( [elementName isEqualToString:@"GetWeatherResult"])
    {
        if (!soapResults)
        {
            soapResults = [[NSMutableString alloc] init];
        }
        elementFound = YES;
    }
    else if([elementName isEqualToString:@"Location"])
    {
        elementFound = YES;
    }   
}

-(void)parser:(NSXMLParser *) parser foundCharacters:(NSString *)string
{
    if (elementFound)
    {
        [soapResults appendString: string];
    }   
}

-(void)parser:(NSXMLParser *)parser 
        didEndElement:(NSString *)elementName 
        namespaceURI:(NSString *)namespaceURI 
        qualifiedName:(NSString *)qName
{
    if ([elementName isEqualToString:@"GetWeatherResult"])
    {   
        NSLog(soapResults);        
        UIAlertView *alert = [[UIAlertView alloc] 
                              initWithTitle:@"Current Temperature!"                                                                                   
                              message:soapResults 
                              delegate:self  
                              cancelButtonTitle:@"OK" 
                              otherButtonTitles:nil];
        [alert show];
        [alert release];
        [soapResults setString:@""];
        elementFound = FALSE; 
    }
}

@end

1
你能发一下代码中进行转换的那部分吗?错误可能是由于设置了不正确的编码,但没有代码很难说。 - bontoJR
确实,我们需要看到您如何检索数据,然后才能提供帮助。 - Matt Gibson
1个回答

2
我已经编辑了您的问题,以便它显示您意图复制的内容。看起来网络服务正在将整个XML文件封装为另一个XML标记内的字符串。所以您需要做的就是将<GetWeatherResult> XML标签的整个内容作为单个字符串获取。我认为NSXMLParser会自动替换正确的字符,代替&gt;等字符。
获得该字符串后,您需要将其传递到另一个NSXMLParser中以解析其中的内容。

我在头文件中添加了新的NSXMLParser *weatherXmlParser;。在didEndElement方法中,当我获取到有效的XML时,我将其存储在NSMutableString *soapResults;变量中,并尝试解析它:if (weatherXmlParser) { [weatherXmlParser release]; } weatherXmlParser = [[NSXMLParser alloc] initWithData: soapResults]; [weatherXmlParser setDelegate:self]; [weatherXmlParser setShouldResolveExternalEntities:YES]; [weatherXmlParser parse];但是我收到了以下错误信息:“terminate called after throwing an instance of 'NSException' Program received signal: “SIGABRT”。 - 1110
你需要将soapResults转换为NSData。 - JeremyP
我很抱歉,因为我很无聊 :(. 我添加了 "NSData *wData = [soapResults dataUsingEncoding:NSUTF8StringEncoding]; NSLog(wData);" 但是我收到了新的错误: "terminate called after throwing an instance of 'NSException' Program received signal: “SIGABRT”. "。之后,此解析方法未被调用。 - 1110
你不能像那样 NSLog 一个数据对象。你必须这样做:NSLog(@"%@", wData); - JeremyP
有没有不需要双重解析数据的方法来解决这个问题,因为我也遇到了同样的问题。 - Mahesh Babu
@MaheshBabu:不,这是最容易的方法,因为从根本上讲,您确实有一个封装在另一个内部的XML字符串。 - JeremyP

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接