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]
Related
I have a very simple xml file by name options.xml
<Dat>
<Name>Tom</Name>
<Option>1</Option>
</Dat>
Using NSXML I am trying to change "Tom" to "Jim" and save the file. How can I do that. I read many document and there is no straight forward solution. Can some one help me with the code ?
update: I ended up in trying with Gdatasxml
-(void)saveToXML
{
NSString* path = [[NSBundle mainBundle] pathForResource:#"options" ofType:#"xml"];
NSData *xmlData = [[NSMutableData alloc] initWithContentsOfFile:path];
NSError *error;
GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:xmlData options:0 error:&error];
GDataXMLElement *rootElement = [GDataXMLElement elementWithName:#"Dat"];
NSArray *mySettings = [doc.rootElement elementsForName:#"Dat"];
for (GDataXMLElement *mySet in mySettings)
{
NSString *name;
NSArray *names = [mySet elementsForName:#"Name"];
if (names.count > 0)
{
GDataXMLElement *childElement = (GDataXMLElement *) [names objectAtIndex:0];
name = childElement.stringValue;
NSLog(childElement.stringValue);
[childElement setStringValue:#"Jim"];
}
}
[xmlData writeToFile:path atomically:YES];
}
But this is not saving the data. Help.
Editing XML is a little difficult in iOS. You need to parse the original xml to a model and then form the xml.
You can make use of 3rd party library such as GDataXML for forming XML from a data source.
//Edited user info saved in a dictionary
NSDictionary *dictionary = #{#"Name": #"Jim", #"Option":#"1"};
GDataXMLElement *rootElement = [GDataXMLElement elementWithName:#"Dat"];
[dictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
GDataXMLElement *element = [GDataXMLElement elementWithName:key stringValue:obj];
[rootElement addChild:element];
}];
//xml document is formed
GDataXMLDocument *document = [[GDataXMLDocument alloc]
initWithRootElement:rootElement];
NSData *xmlData = document.XMLData;
NSString *filePath = [self savedXMLPath];
//XML Data is written back to a filePath
[xmlData writeToFile:filePath atomically:YES];
Create a class that is essentially an XML "node". Then in your parser setup a system of these XML nodes in the same fashion as you read them. Then search through that body and find the element that you would like to change. Change it. Then write a function that goes through these "node" objects and writes a new NSString in XML format and save that string to file. There is no real easy way that I know of to write XML files. I'm sure someone has a library out there to do it, but I had very complex XML's to deal with so I wrote my own. If you would like specific code let me know and I can try to give you parts of what you may need.
You Can use GDATAXML for changing XML node
Here is Working Code snippet
NSString *XMLString = #"<Dat><Name>Tom</Name><Option>1</Option></Dat>";
NSError *error = nil;
GDataXMLElement *newElement = [[GDataXMLElement alloc] initWithXMLString: XMLString error: &error];
NSLog(#"New element: %# error: %#", newElement, error);
if(nil == error)
{
GDataXMLElement *childElement = [[newElement elementsForName: #"Name"] objectAtIndex: 0];
[childElement setStringValue:#"Jim"];
childElement = [[newElement elementsForName: #"Option"] objectAtIndex: 0];
[childElement setStringValue:#"2"];
}
NSLog(#"New element now: %#", newElement);
Check by using this code snippet
I want to parse rss that have child with the same name but different value. In this case, i want to parse the value from child name 'category'.
Here's the RSS Format:
<item><title>HAC Algorithm by holiccorp</title>
<link>http://www.freelancer.com/projects/PHP-Javascript/HAC-Algorithm.html</link>
<description>Need someone good at javascript coding and HAC Algorithm. I need someone to create and analyze the code,script and logic. More details will be given after discussion. ASAP project. (Budget: $30-$250 USD, Jobs: Algorithm, HTML, Javascript, PHP, Website Testing)</description>
<pubDate>Sun, 23 Sep 2012 13:20:17 -0400</pubDate>
<guid isPermaLink="false">Freelancer.com_project_2509687</guid>
<category domain="http://www.freelancer.com/jobs/">Algorithm</category>
<category domain="http://www.freelancer.com/jobs/">HTML</category>
<category domain="http://www.freelancer.com/jobs/">Javascript</category>
<category domain="http://www.freelancer.com/jobs/">PHP</category>
<category domain="http://www.freelancer.com/jobs/">Website Testing</category>
<coop:keyword>Algorithm</coop:keyword>
<coop:keyword>HTML</coop:keyword>
<coop:keyword>Javascript</coop:keyword>
<coop:keyword>PHP</coop:keyword>
<coop:keyword>Website Testing</coop:keyword>
<coop:keyword>project 2509687</coop:keyword>
<coop:keyword>HAC Algorithm</coop:keyword>
</item>
I did something like this:
NSArray *channels = [rootElement elementsForName:#"channel"];
for (GDataXMLElement *channel in channels) {
NSString *blogTitle = [channel valueForChild:#"title"];
NSLog(#"blogTitle %#",blogTitle);
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"];
NSString *articleDescription = [item valueForChild:#"description"];
NSDate *articleDate = [NSDate dateFromInternetDateTimeString:articleDateString formatHint:DateFormatHintRFC822];
NSDate *timeStamp = [NSDate date];
NSString *category = [item valueForChild:#"category"];
}
Fron this code, I got only first value from child name category. How do i parse all value from this child and show in one line? Any idea?
Many Thanks
You have to study more about GDataXML attribute parsing methods
The below links may help you
example-code-for-parsing-xml-and-get-attributes
parsing-xml-attribute-using-gdataxmldocument
see the GData example here
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];
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!
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!