iam developing one application.In that iam using the xml parsing.That xml file contain the 4 category tags and other tags.From the xml file i want to get the data of category tag.At the time of getting the category data,every time i print the array of category values.That show correctly.But after completion of parsing, another tag data will be append to last category name.My parsing code is like below.
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if(self.presentvalue)
{
[presentvalue appendString:string];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if(![elementName compare:#"category"])
{
[categories addObject:presentvalue];
NSLog(#"%#",presentvalue);
NSLog(#"Number of elements %#",categories);
}
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
if([elementName isEqualToString:#"category"])
{
presentvalue=[NSMutableString string];
}
}
And my xml file content is like
<lesson>
<categories>
<category id="1">1</category>
<category id="2">2</category>
<category id="3">3</category>
</categories>
<references>
<reference id="1" type="youtube" categoryid="2" name="Boyles law">
<url><![CDATA[http://www.youtube.com/watch?v=J_I8Y-i4Axc]]>
</url>
</reference>
</references>
</lesson>
From this xml i got the array values like 1,2,3http://www.youtube.com/watch?v=J_I8Y-i4Axc.Like this i got the result.So please tell me how to get the category values without that extra data.
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
if ([elementName isEqualToString:#"category"]) {
NSLog(#"Node is found correctly");
if(presentvalue == nil)
presentvalue = [NSMutableString string];
else
[presentvalue setString:#""];
}
else {
presentvalue = nil;
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
[presentvalue appendString:string];
if (presentvalue)
{
[self.tempArray addObject:presentvalue]; // add this line. create a tempArray containing all the strings.
presentvalue = nil;
}
}
this should help u in your parsing. hope it helps. happy coding :)
place check in your xml parsing code. that if the starting/ending element name is category. add objects to array else do nothing. just passout
I think this line look strange
if(![elementName compare:#"category"])
Shouldn't it be like this? (without !)
if([elementName compare:#"category"])
edited
Try replacing this to the didEndElement
if([elementName isEqualToString:#"category"])
{
[categories addObject:presentvalue];
presentValue = [NSMutableString string];
NSLog(#"%#",presentvalue);
NSLog(#"Number of elements %#",categories);
}
Related
I want to set string "EMPTY"for empty tag XML in NSXMLParse. Exm: my xml:
<STATE>0</STATE>
<MEMO/>
In above XML, MEMO tag is empty. I want to when NSXMLParse parse into tag, if it is empty,get string "EMPTY" in label. I used bellow code to parse xml:
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict
{
NSLog(#"Did start element");
if ( [elementName isEqualToString:#"FILENAME"])
{
XML_FIELD = FILENAME_CLOUD2;
NSLog(#"found rootElement");
return;
}
else if ( [elementName isEqualToString:#"MEMO"])
{
NSLog(#"found rootElement");
XML_FIELD = MEMO;
return;
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
NSLog(#"Did end element");
if ([elementName isEqualToString:#"FILENAME"])
{
NSLog(#"rootelement end");
}
[strMemoEmpty setString:#"EMPTY"];
XML_FIELD = UNIMPORTANT2;
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
//NSString *tagName = #"USER_NAME";
if (XML_FIELD == FILENAME_CLOUD2)
{
NSLog(#"Value %#",string);
[FileCompletedArray insertObject:string atIndex:0];
}
else if (XML_FIELD == MEMO)
{
NSLog(#"Value %#",string);
if (string != nil) {
[strMemoEmpty setString:#""];
[strMemoEmpty appendString: string];
NSLog(#"foundResults: %#",strMemoEmpty);
}
[MemoArray insertObject:string atIndex:0];
}
}
I used above code but it not check MEMO tag is empty. It missed when parse. Do you have any suggestions? Thanks in advance
The construction of your code is a bit strange and messy, you should reorganise so:
didStartElement creates new storage for the starting element and sets any flags
foundCharacters doesn't have logic, it just appends the received string to a mutable buffer (it could be called multiple times for the same tag)
didEndElement contains the logic (and checks the length of the found characters and substitutes your empty value if required)
The way you have it now means that partial data may be saved in foundCharacters and, because that method isn't called for empty tags, some of your logic is being set but never actually saved.
Please anybody help me.i am in great trouble....Now my Problem is...
Using xml parser i have parsed some attribute and value of the attribute.
using this i am getting the element name:
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes: (NSDictionary *)attributeDict
Now using this i am getting value of the attribute from the xml:
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
NSLog(#"found characters: %# %#", currentElement,string);
suppose my xml data are something like that...
-<list>
−<ProductData HASH="838557843">
<id>1</id>
<productNumber>a91cc0f4c7</productNumber>
<name>Product 1</name>
<seoTitle>product-1</seoTitle>
<viewCount>0</viewCount>
<lowStock>0.0</lowStock>
<image>5e928bbae358c93caedf6115fa7d178b.jpg</image>
<dateCreated>2011-10-06T16:08:45</dateCreated>
<dateUpdated>2011-10-06T10:08:45</dateUpdated>
<isDummy>true</isDummy>
<isInventory>false</isInventory>
</ProductData>
-<ProductData HASH="681596439">
<id>2</id>
<productNumber>d8287e2e51</productNumber>
<name>Product 2</name>
<seoTitle>product-2</seoTitle>
−<description>
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit,....</p>
</description>
<viewCount>0</viewCount>
<availableStock>100.0</availableStock>
<lowStock>0.0</lowStock>
<image>8bbd8dfff3cdd28285d07810a4fe7c32.jpg</image>
<basePrice>10.0</basePrice>
<costPrice>10.0</costPrice>
<height>1.0</height>
<width>1.0</width>
<depth>1.0</depth>
<weight>3.0</weight>
<status>A</status>
<quantityOrderMin>1.0</quantityOrderMin>
<productIsCall>false</productIsCall>
<quantityOrderMax>20.0</quantityOrderMax>
<priceByAttribute>false</priceByAttribute>
<dateCreated>2011-10-06T16:08:45</dateCreated>
<dateUpdated>2011-10-06T10:08:45</dateUpdated>
<isDummy>true</isDummy>
<isInventory>false</isInventory>
</ProductData>
</list>`
Now when i will get the id attribute then it will store in an array then all of the attribute after first id until next id i want to store the attribute and its value in the dictionary,when i will get second id then i want to continue previous process...then according to the value of id i want to display the value in a UIView or UITableView. its not neccesary where i want to display it.
My question is how can i store data in array and dictionary and display it any time in my viewcontroller. Please help me. its becoming a great trouble for me. if you can please give me a sample code as an example. please please anybody help me...
Thanks in Advance
If you change your XML to
<list>
<Object>
<id>1</id>
<product>name</product>
<image>imagename.jpg</image>
<dateCreated>date</dateCreated>
<productleft>10</productleft>
</Object>
<Object>
<id>2</id>
<product>name</product>
<image>imagename.jpg</image>
<dateCreated>date</dateCreated>
<productleft>30</productleft>
</Object>
</list>
Or if your XML looks something like above its easy to use SAX parser ( NSXMLParser you've used ). Otherwise if you want to stick to XML you have posted use DOM style parsing.
Here is the code for the XML after formatting using NSXMLParser.
// these are ivars
NSMutableArray * objectsArray;
NSMutableDictionary * productDict;
NSMutableString * currentString;
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict
{
if([elementName isEqualToString:#"Object"])
{
objectsArray = [[NSMutableArray alloc] init];
productDict = [[NSMutableDictionary alloc] init];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if(!currentString)
{
currentString = [[NSMutableString alloc] init];
}
[currentString appendString:string];
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if([elementName isEqualToString:#"id"])
{
[productDict setObject:currentString forKey:#"id"];
[currentString release],currentString = nil;
return;
}
if([elementName isEqualToString:#"product"])
{
[productDict setObject:currentString forKey:#"product"];
[currentString release],currentString = nil;
return;
}
if([elementName isEqualToString:#"image"])
{
[productDict setObject:currentString forKey:#"image"];
[currentString release],currentString = nil;
return;
}
if([elementName isEqualToString:#"dateCreated"])
{
[productDict setObject:currentString forKey:#"dateCreated"];
[currentString release],currentString = nil;
return;
}
if([elementName isEqualToString:#"productleft"])
{
[productDict setObject:currentString forKey:#"productleft"];
[currentString release],currentString = nil;
return;
}
if([elementName isEqualToString:#"Object"])
{
[objectsArray addObject:productDict];
[productDict release],productDict = nil;
}
[currentString release], currentString = nil;
}
I'm newbie on iPhone development.I want to parse XML file like this to get attribute value.
<Root>
<element att_1 ="value1" att_2 ="value2" />
<element att_1 ="value1" att_2 ="value2" />
.
.
.
<Root/>
Normally XML file
<element att="..."> content <element/>
I use this at didEndElement
if([elementName isEqualToString:#"element"]){
// Do something
}
How to check empty tag ? Advice me Please.
Thank you.
sorry for my bad english.
=====================================================================
Now I have new problem.when I run the application(simulator) it stuck and show message"Thread1:Stopped at breakpoint" in didStartElement.I guess I do something wrong.
StudyList.xml
<StudyList>
<study description="20040311181130" modsInStudy="" pat_birth="19760822" pat_id="47-3450" pat_name="Ekachai Chaichanasiri" refPhy="" study_date="Sun Jan 11 00:03:00 ICT 2004" study_id="696122224" study_iuid="1.2.392.200036.9123.100.200.20040311181130"/>
<study description="XoranCAT Study" modsInStudy="" pat_birth="19821117" pat_id="63" pat_name="Wantana Areeprayolkij" refPhy="" study_date="Fri Jan 28 00:04:00 ICT 2005" study_id="" study_iuid="1.2.826.0.1.3680043.2.594.4041.16900.9840.32723.30648"/>
</StudyList>
Delegate
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
if ([elementName isEqualToString:#"StudyList"]) {
//Initialize the array.
appDelegate.studyList = [[NSMutableArray alloc] init];
} else if ([elementName isEqualToString:#"study"]) {
//Initialize the study.
aStudy.patientBrith = [attributeDict objectForKey:#"pat_birth"] ;
aStudy.patientID = [attributeDict objectForKey:#"pat_id"];
aStudy.patientName = [attributeDict objectForKey:#"pat_name"];
aStudy.studyDate = [attributeDict objectForKey:#"study_date"];
NSLog(#"Patient name: %#",aStudy.patientName);
NSLog(#"Patient ID: %#",aStudy.patientID);
NSLog(#"Patient Birth: %#" ,aStudy.patientBrith);
NSLog(#"Study Date: %#" ,aStudy.studyDate);
}
NSLog(#"Process Element");
}
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
//Nothing to do because XML file dose not have text node
}
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
//End if XML file nothing to do.
if ([elementName isEqualToString:#"StudyList"]) {
return;
//Add study object in to array and release the object.
if ([elementName isEqualToString:#""]||elementName == nil) {
[appDelegate.studyList addObject:aStudy];
}
}
}
NSLog(#"Patient name: %#",aStudy.patientName);
NSLog(#"Patient ID: %#",aStudy.patientID);
NSLog(#"Patient Birth: %#" ,aStudy.patientBrith);
NSLog(#"Study Date: %#" ,aStudy.studyDate);
***Output of above is null.
What wrong,Please tell me in right way.
Retain the value of string in this function
- (void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
In - (void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
Check
if ([retainedString isEqualToString:#"" ] || [retainString == nil)
Then the value is empty.
I'm using NSXMLParser to parse an XML file. I'm doing this several times in my app for different purposes. I have one which parses annotations for a store locator, one that parses al the movies from a certain YouTube channel and the last one parses a self made XML file.
All parsers work great except the last one. For some kind of reason it parses i.e. the first node good, but then overwrites it.
Here is my parser code:
//Standard function parser: reading open tag
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
attributes:(NSDictionary *)attributeDict{
currentElement = [elementName copy];
if ([elementName isEqualToString:#"item"]) {
xmlArray = [[NSMutableDictionary alloc] init];
}
}
//Standard function parser: reading string
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
if ([currentElement isEqualToString:#"created_time"]){
[xmlArray setObject:string forKey:currentElement];
NSLog(#"test 1 %#", string);}
}
//Standard function parser: reading close tag
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName{
if ([elementName isEqualToString:#"item"]) {
Post *newPost = [[Post alloc] init];
NSLog(#"test %#", xmlArray );
newPost.created_time = [xmlArray objectForKey:#"created_time"];
[containerArray addObject:newPost];
[xmlArray release];
}
}
The XML looks like this:
<?xml version="1.0" encoding="UTF-8" ?>
<items>
<item>
<created_time>test</created_time>
<message>blabla</message>
<picture>http://www.trentshow.com/images/tada.jpg</picture>
</item>
</items>
And the log outputs the following:
2011-06-10 10:43:24.446 TabbedCalculation[1502:207] test 1 test
2011-06-10 10:43:24.448 TabbedCalculation[1502:207] test 1
2011-06-10 10:43:24.449 TabbedCalculation[1502:207] test 1
2011-06-10 10:43:24.450 TabbedCalculation[1502:207] test {
"created_time" = "\n";
}
I'm not getting why the parser loops 3 times over the created_time node. Any help would be great!
Try by following solution -- should work.
foundCharacters can be called for multiple time for each key value --- basically you should append all found character list.
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
if ([currentElement isEqualToString:#"created_time"]){
NSString *valueKey = [xmlArray ValueForKey:forKey:currentElement];
if(nil != valueKey)
{
valueKey = [valueKey stringByAppendingString:string];
}else
{
valueKey = string;
}
[xmlArray setObject:valueKey forKey:currentElement];
NSLog(#"test 1 %#", string);}
}
I am using NSXMLParser to parse this XML: http://itunes.apple.com/gb/rss/topsongs/limit=50/explicit=true/xml. I am trying to parse an element called "im:image". My problem is that there are three elements with the name "im:image". How can I only parse the data from the second "im:image", or how can I add each single one to an array?
This is probably not the best way to do it, but when something like this happened to me I simply created a NSInteger named counter. Then in didStartElement I did this: (I was looking for the second element in my case)
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict {
if([elementName isEqualToString:#"yweather:forecast"])
{
int code = [[attributeDict objectForKey:#"code"] intValue];
if (counter == 0) {
}
if (counter == 1) {
conditionCode = code;
}
counter ++;
}
}
In the didStartElement method of your custom delegate, check attributes and ensure that it has height set to 60 (each of the 'same' XML elements has a different height attribute). The attributes is an NSDictionary with keys for name of the attributes and values for values of the attributes. Here is an example of roughly how you would do it:
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict {
if ([[attributeDict objectForKey:#"height"] isEqualToString:#"60"]) {
NSLog(#"store");
}
}