Parsing XML on iPhone with GDataXML - iphone

Ugh, I'm having a dickens of a time parsing xml from Exchange Web Services. I want to get the ItemID Id=xyz attribute (AAATAG...). Here is the XML:
<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:Header><t:ServerVersionInfo xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" MajorVersion="8" MinorVersion="3" MajorBuildNumber="137" MinorBuildNumber="0"/></soap:Header><soap:Body><m:FindItemResponse xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"><m:ResponseMessages><m:FindItemResponseMessage ResponseClass="Success"><m:ResponseCode>NoError</m:ResponseCode><m:RootFolder TotalItemsInView="1" IncludesLastItemInRange="true"><t:Items><t:CalendarItem><t:ItemId Id="AAATAGNvb3Blcm1qQG11b2hpby5lZHUARgAAAAAA+Q4xQgA/2kCus7bZbZddngcA8vxBsULRa0S+uFR566ChHwAAAB4BwgAABgoCL+IgvEaj+O0Bl9BG2AAQEOyJMwAA" ChangeKey="DwAAABYAAAAGCgIv4iC8RqP47QGX0EbYABARELYs"/><t:Organizer><t:Mailbox><t:Name>Cooper, Micah</t:Name></t:Mailbox></t:Organizer></t:CalendarItem></t:Items></m:RootFolder></m:FindItemResponseMessage></m:ResponseMessages></m:FindItemResponse></soap:Body></soap:Envelope>
I'm using GDataXML, and here is my code:
- (void)parseFeed:(GDataXMLElement *)doc entries:(NSMutableArray *)entries {
NSLog(#"%#", doc);
NSDictionary *namespaceMappings = [NSDictionary dictionaryWithObjectsAndKeys:#"http://schemas.microsoft.com/exchange/services/2006/messages", #"messages",
#"http://schemas.microsoft.com/exchange/services/2006/types",#"types", nil];
NSArray *items = [doc nodesForXPath:#"//types:CalendarItem" namespaces:namespaceMappings error:nil];
for (GDataXMLElement *item in items) {
NSLog(#"Item: %#", item.stringValue);
NSString *itemID = [[item attributeForName:#"ItemId Id"] stringValue];
NSLog(#"itemID: %#", itemID);
}
}
I'm not pulling the item id -- in fact, it looks as if it is parsing at random places in the XML. Can anyone point me in the right direction? Thanks!

Related

create NSString in xml format as request to webserver in iphone sdk?

I need to create an NSString in xml format, so that I need to send it as a web service request.
I have created the xml structured NSString using this code
NSMutableString *res = [NSMutableString string];
[res appendString:#"<question>"];
[res appendFormat:#"<productid>%#</productid>", [array objectAtIndex:0]];
[res appendFormat:#"<questionid>%#</questionid>", [array objectAtIndex:1]];
[res appendFormat:#"<valueid>%#</valueid>", [array objectAtIndex:2]];
[res appendFormat:#"<answerText>%#</answerText>", [array objectAtIndex:3]];
[res appendFormat:#"</question>"];
but, when I send this as a request ( web service code created using sudzc) , I got some errors
Entity: line 1: parser error : Start tag expected, '<' not found
Bad Request
Error: The operation couldn’t be completed. (CXMLErrorDomain error 1.)
this is my sending string
NSString *send=[NSString stringWithString:#"<request><ProductName>ppr</ProductName><questionid>fff</questionid><answerText>%#</answerText></request>"];
what all the tags should i replace while creating string xml?
here is my request,,
[service CreateRequest:self action:#selector(CreateRequestHandler:) Email:#"xxxx" Password:#"anoopgopalan" Token:#"xxx" Request:send];
- (void) CreateRequestHandler: (id) value {
// Handle errors
if([value isKindOfClass:[NSError class]]) {
NSLog(#"%#", value);
return;
}
// Handle faults
if([value isKindOfClass:[SoapFault class]]) {
NSLog(#"%#", value);
return;
}
// Do something with the MFLAPIError* result
MFLAPIError* result = (MFLAPIError*)value;
NSLog(#"CreateRequest returned the value: %#", result);
}
You are missing some tags in the resulted xml string.. any xml response from web services will be as the below..
Your xml must be embedded with in this..
<?xml version="1.0" encoding="utf-8"?>
<root>
//your generated xml with tags
</root>

iPhone Parsing Enclosure url tag?

I am having an issue with a blog I am working on. The method I am using to parse is:
NSArray *channels = [rootElement elementsForName:#"channel"];
for (GDataXMLElement *channel in channels)
{
NSString *blogTitle = [channel valueForChild:#"title"];
NSArray *items = [channel elementsForName:#"item"];
for (GDataXMLElement *item in items)
{
NSString *articleTitle = [item valueForChild:#"title"];
NSString *articleUrl = [item valueForChild:#"link"];
NSString *articleDateString = [item valueForChild:#"pubDate"];
}
}
EDIT: XML LOOKS LIKE:
<item>
<title>Your Direction Determines Your Destination</title>
<link>http://treymorgan.podbean.com/2012/06/05/your-direction-determines-your-destination/</link>
<comments>http://treymorgan.podbean.com/2012/06/05/your-direction-determines-your-destination/#comments</comments>
<pubDate>Tue, 05 Jun 2012 17:57:07 +0000</pubDate>
<dc:creator>treymorgan</dc:creator>
<category></category>
<guid isPermaLink="false">http://treymorgan.podbean.com/2012/06/05/your-direction-determines-your-destination/</guid>
<description><![CDATA[Part 1 of the series … Road Trip
]]></description>
<content:encoded><![CDATA[<p>Part 1 of the series … Road Trip
</p>
]]></content:encoded>
<wfw:commentRss>http://treymorgan.podbean.com/2012/06/05/your-direction-determines-your-destination/feed/</wfw:commentRss>
<enclosure url="http://treymorgan.podbean.com/mf/feed/x52488/DirectionDeterminesyourDestination.mp3" length="32015229" type="audio/mpeg"/>
</item>
This way I can get the title of the article from the Title tag within the XML. Most xmls I have parsed have included the mp3, either in the "guid" or "link" tag. However, the current feed I am working with, looks like this:
<enclosure url="http://treymorgan.podbean.com/mf/feed/bf8mvq/Accommoditions.mp3" length="29865594" type="audio/mpeg"/>
How can I pass the url from the enclosure into an NSString?
Something like [[item attributeForName: #"url"] stringValue] should do it. Depending on the actual location of the enclosure element in the XML tree, you might need to use another element instead of channel of course.
Answer is
[[[[item elementsForName: #"enclosure"] lastObject] attributeForName: #"url"] stringValue]

how to implements code for get the JSON objects in iphone?

hi all i am a new iphone developer. i am getting response from my required URL as shown in the below here i need to get Name of "CategoryID":1 and Name of "CategoryID":2 both are in separate array sets. how to implements code for get the JSON objects in iphone?. thank you
code for getting response:
theXML = [[NSString alloc] initWithBytes: [RoutData mutableBytes] length:[RoutData length] encoding:NSUTF8StringEncoding];
NSLog(#"---->>>>>>-->>>:%#",theXML);
Response:
LocationTracking[1807:f803] ---->>>>>>-->>>:<?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><getGearLockerCategoriesResponse xmlns="http://tempuri.org/"><getGearLockerCategoriesResult><status>SUCCESS</status><errorType /><errorMessage /><jsonString>[{"CategoryID":1,"ItemCount":1,"level":1,"Name":"Boots","Description":"Boots descrition","childs":[{"CategoryID":2,"ItemCount":1,"level":2,"Name":"Cold Water","Description":"Cold Water Description","childs":[]}]}]</jsonString><serverTimestamp>63477507673796</serverTimestamp></getGearLockerCategoriesResult></getGearLockerCategoriesResponse></soap:Body></soap:Envelope>
<jsonString>
[{"CategoryID":1,"ItemCount":1,"level":1,"Name":"Boots","Description":"Boots
descrition","childs":[{"CategoryID":2,"ItemCount":1,"level":2,"Name":"Cold
Water","Description":"Cold Water Description","childs":[]}]}]
</jsonString>
<serverTimestamp>63477390375625</serverTimestamp>
</DiveTravelerResponse>
The Touch JSON library is a good solution: https://github.com/TouchCode/TouchJSON
NSJSONSerialization. If your JSON is in an NSString named 'str':
NSError *jsonError = nil;
NSArray *rootObjectArray = [NSJSONSerialization JSONObjectWithData:[str dataUsingEncoding:NSUTF8StringEncoding] options:0 error:&jsonError];
if (rootObjectArray)
{
/* you have a foundation object */
}
else
{
/* something went wrong */
NSLog(#"jsonError: %#", [jsonError localizedDescription]);
}

How to parse xml from specific tag

I have a xml file, i can do the parsing using the NSXML parser. Now i want to start parsing from specific tag , how this can be done ?
<RootElement>
<City>
<Name>WC</Name>
<Time>6 am</Time>
<Notes>Hi</Notes>
</City>
<State>
<Name>ABC</Name>
<Time>6 a.m.</Time>
<Time>2 a.m.</Time>
<Notes>This is a note for ABC</Notes>
</State>
<State>
<Name>DEF</Name>
<Time>8 am</Time>
<Time>10 am</Time>
<Notes>This is a note for DEF</Notes>
</State>
</RootElement>
Now the parsing should start from State tag , but it parses entire document and displays the name,time,notes from the City Tag also. Parsing from specified tag , how it can be done ?
Take a look at:
- (NSArray *)nodesForXPath:(NSString *)xpath error:(NSError **)error
EDIT: Code example
NSError* error;
CXMLDocument *doc = [[CXMLDocument alloc] initWithData:Data options:0 error:&error];
// figure out what nodes are in the doc, and pick it apart with the nodesForXPath call
NSArray * results = [doc nodesForXPath:#"/RootElement" error:&error];
NSString * finalUrl = self.defaultURL;
if ( [results count] > 0 ) {
NSString * element = [(CXMLElement *)[results objectAtIndex:0] stringValue];
if ( [element isEqualToString:#"State") {
// Do state processing
}
}
[doc release];

Parsing SOAP result using TouchXML in iOS SDK (iPad)

I'm working on an iPad project that is using functions in a WebService.
Handling webservice connection, data etc works find. But i'm not able to parse the result SOAP using TouchXML. Getting the nodes out of the xml always returns 0 length.
The output 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> <LogOnResponse xmlns="http://coreservices.org/v1"> <LogOnResult> <Id>1c0e9ad0-a3be-4cd0-8f0d-0616a63a4e28</Id> <userId>2</userId> <user> <ID>2 <Name>Beheerder <emailAddress /> <cultureName>nl-NL</cultureName> </user> </LogOnResult> </LogOnResponse> </soap:Body></soap:Envelope>
parser code:
NSData *aData = [[NSData alloc] initWithBytes:[webData mutableBytes] length:[webData length]];
NSString *xmlData = [[NSString alloc] initWithData:aData encoding:NSASCIIStringEncoding];
NSLog(#"%#", xmlData);
[xmlData release];
CXMLDocument *domUserIdentity = [[[CXMLDocument alloc] initWithData:aData options:0 error:nil] autorelease];
[aData release];
NSArray *nodesList = [domUserIdentity nodesForXPath:#"//LogOnResult" error:nil]; // 0 length
for (CXMLElement *resultElement in nodesList) {
for (int counter = 0; counter
NSString *elemName = [[resultElement childAtIndex:counter] name];
NSString * elemValue = [[[resultElement childAtIndex:counter] stringValue] stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]];
[elemName release];
[elemValue release];
}
}
[nodesList release];
Any idea what did i do wrong?
Thank's alot in advance.
Inoel
Try using the NSXMLDocument, it should work as well as CXMLDocument. Here are some docs:
link
I recommend using an XPath Parser. You aren't doing anything too heavy, so the speed hit is well worth it. My personal choice is TFHpple. There are slightly faster and more precise solutions out there, but I find TFHpple's simplicity hard to beat.
Example:
NSData *data = [[NSData alloc] initWithContentsOfFile:#"example.html"];
// Create parser
xpathParser = [[TFHpple alloc] initWithXMLData:data];
NSArray *elements = [xpathParser search:#"//LogOnResult"];
TFHppleElement *element = [elements objectAtIndex:0];
// Get the text within the cell tag
NSString *content = [element content];
[xpathParser release];
[data release];
Obviously you'd have to write some code to save the parts you want. Looking at this data, I'd probably make a custom data holder class that you can access with properties. You can parse your XML into that and then save it as a property in the view controller that will be accessing it.
Happy coding!