xml parsing in iPhone and getting other tags with same names - objective-c

Let me try to explain as clear as possible what I mean exactly with this question.
The xml looks instead like this
<Books>
<Book id="1">
<title>Circumference</title>
<author>Nicholas Nicastro</author>
<summary>Eratosthenes and the Ancient Quest to Measure the Globe.</summary>
</Book>
<Book id="2">
<title>Copernicus Secret</title>
<author>Jack Repcheck</author>
<summary>How the scientific revolution began</summary>
</Book>
</Books>
It will look like this
<Books>
<Book id="1">
<title>Circumference</title>
<author>Nicholas Nicastro</author>
<summary id ='1'>Eratosthenes and the Ancient Quest to Measure the Globe.</summary>
<summary id ='2'>Eratosthenes more info in another tag.</summary>
<summary id ='3'>Eratosthenes and again another tag.</summary>
<summary id ='4'>Eratosthenes and the final tag another one here</summary>
</Book>
<Book id="2">
<title>Copernicus Secret</title>
<author>Jack Repcheck</author>
<summary id ='1'>How the scientific revolution began</summary>
<summary id ='2'>Eratosthenes more info in another tag.</summary>
<summary id ='3'>Eratosthenes and again another tag.</summary>
<summary id ='4'>Eratosthenes and the final tag another one here</summary>
</Book>
</Books>
Now if I follow the instruction on the site listed above , it doesn't explain how to handle summary 2,3,4( the xml i need to parse looks like that) and how I can show their output. All I will get is the last line. Does anyone have an idea about how I can get the other ones as well( meaning 2,3 in this case it seems to show only the last one since that's probably the last in the currentElementValue ).
I'm a bit confused would I have to address the attribute here as well or should I create a new search tag in my parser?

I think this is what you need to be looking at, you could grab the value of the id field from the attributes and using that value assign it to a variable which you can then use.
So I might have something this in my didStartElement (where attributes is a variable declared in the header):
if([elementName isEqualToString:#"Summary"]){
attributes = attributeDict;
}
Then something like this in my foundCharacters:
if([[attributes valueForKey:#"id"] intValue] == 1){
doSomething
}else if([[attributes valueForKey:#"id"] intValue] == 2){
doSomethingElse
}...
and so on until you've got all your data out.
N.B. This is 100% untested code but I'm confident it might work...

You will need to keep track of the summary elements you have parsed so far by keeping all the values in some container like an array: NSMutableArray. Thus, instead of an NSString to keep the summary, you'd have an NSMutableArray to hold the list of summaries you have parsed.
Whenever you encounter a summary in your parser, you don't set the NSString summary to the string you just read (which replaces the old value and explains why you only get the last summary tag). Instead, you store it as a new string and add that string to your NSMutableArray.
The problem with the design in the blog post you linked to is that it uses keyValueCoding to set the properties in the Book object and that doesn't facilitate adding items to an array item very well. Hence, you will need to include some special handling for the summary element in the parser and add methods to the Book class that allow you to add items to the summary array. See this post on how to also do that with KVC.

Related

Business validation in mulesoft

I want to do field level validation in mule, i am able do the schema validation but stuck in field level validation for example first name should be string and not empty and date of birth should in be in integer format and not empty etc..
I am attaching my sample file , i know there is a component ( validation) which do such type of validation but i have many filed in XML ( here i have attached simple XML file due to security issues),which is basically called business validation.
Kindly help me how to do such type of validation in mule.
<?xml version="1.0"?>
<x:books xmlns:x="urn:books">
<book id="bk001">
<author>Writer</author>
<title>The First Book</title>
<genre>Fiction</genre>
<price>44.95</price>
<pub_date>2000-10-01</pub_date>
<review>An amazing story of nothing.</review>
</book>
<book id="bk002">
<author>Poet</author>
<title>The Poet's First Poem</title>
<genre>Poem</genre>
<price>24.95</price>
<review>Least poetic poems.</review>
</book>
</x:books>
Cheers,
Isr
Kindly refer to below link. you can use validations module i has predefined set of validations.
https://docs.mulesoft.com/mule-user-guide/v/3.7/validations-module
EX: To validate a field is not empty. use this validator module.
<validation:is-not-empty expression="#[(xpath expression goes here)/]" />
If it doesn't match your expectations then using Xpath parse the respective fields and use an expression component to do all these validations.
Thanks!

passing model back to controller with checkboxes comes back empty

trying to grasp how to pass back the following data as a model to the controller. I want to consume the model and add everything to a database afterwards. When I submit the form back to the controller, the model is empty. Is it because every thing else is null? do I have to pass everything else back as hidden fields? How do I sort that all out on the View before getting to the controller?
My controller basically deserializes an xml file that looks like this back to the view
<category>
<id>1</id>
<description>movies</description>
<genre>
<genres>
<id>1</id>
<name>comedy</name>
</genres>
<genres>
<id>2</id>
<name>action</name>
</genres>
<genres>
<id>3</id>
<name>adventure</name>
</genres>
<genres>
<id>4</id>
<name>drama</name>
</genres>
<genres>
<id>5</id>
<name>romance</name>
</genres>
</genres>
</category>
The view / form looks like this
<form>
<ul>
#for (int x = 0; x < Model.categories[i].genres.Count(); x++)
{
<li>
<label for="#Model.categories[i].genres[x].name">
<input type="checkbox" name="#Model.categories[i].genres[x].name" value="#Model.categories[i].genres[x].id" checked="#Model.categories[i].genres[x].selected" /> #Model.categories[i].genres[x].name
</label>
</li>
}
</ul>
</form>
Give all your checkboxes a fixed name, like GenreIds.
Then, in your action you should receive a string[] genreIds parameter.
When posting the form, the genreIds is posted as am array, so it must be received in an array parameter.
If this doesn't work because you have many categories and want to receive each group of GenreIds in its own category, then you can send a JSON representation of the form values and receive and deserialize it on the server side. To do so:
On the razor template:
Use the name of the genre to name all the checkboxes in each category
Handle the form sumit event, and:
Use jQuery serializeArray, to put all the form elements in an array
Then use JSON.stringify to convert this array to JSON format
Finally copy this string to a hidden field with a fixed name and post the form. I.e. in a hidden field with the name "serializedFormValues"
On the server side:
Add a parameter to your action with the name "serializedFormValues", and type = string
get the value of this parameter and deserialize the received JSON string, and use it on the server side
If you use JSON.NET you can convert the JSON to XML, or to an anonymous type object. There are another posibilities.
Remember that in any case, the genre Ids will always be string[] (or int, if ti's the case) and this arrays will only contain the checked values.
There is a last posibility which is processing the Request.Form "manually". But this is harder to do.
Try using CheckboxFor instead of the input tag.
As for your code, you don't have an ID associated with your checkbox. How are you supposed to be receiving it back in your controller?

Hpple - Reading a tag with an attribute

I'm trying to parse a XML,
<entry>
<title type="html"><![CDATA[TITLE]]></title>
</entry>
Using Hpple, I'm trying to read the
NSArray *array = [xpathParser searchWithXPathQuery:#"//entry/title[#type='html']"];
But the returned value is null. What I'm doing wrong?
As hpple is a wrapper over XPathQuery, you might want to check it this answer
tl;dr Try adding /text() to your XPath query.
Also it looks like Hpple's author uses a different function call to search by XPath in his Unit Test for hpple; for example NSArray * a = [doc search:#"//a[#class='sponsor']"];, perhaps its worth to give that a shot.

SimpleXML save tag content as variable

OK I've been working with tag attributes up to now, but what if I want to save the actual contents of a tag as a variable, how would I do that?
For instance, in the example below, how would I save 'John' to a variable?
<person>
<name>John</name>
</person>
Thanks!
You're talking about SimpleXML in PHP?
$xml = new SimpleXMLElement('<?xml version="1.0" encoding="utf-8" ?><person><name>John</name></person>');
$john = $xml->name ;
echo $john ;
The reason we use $xml->name in our example rather than $xml->person->name is that SimpleXML will assume the root element (worth keeping in mind :). In a real example the XML would have a different root element, with perhaps several <person> elements, which you then could get by array notation, as in ;
$james = $xml->person[4]->name ;
A more powerful way is to use Xpath which is worth looking into for better dealing with complex XML ;
$john = $xml->xpath ( 'person/name' ) ;
Using PHP, you can do it in this way:-
<?php
$xmlstr = <<<XML
<person>
<name>John</name>
</person>
XML;
$xml = new SimpleXMLElement($xmlstr);
$name_person = $xml->name;
// If you are unsure about the node string, then it's best to write it as:-
$name_person = $xml->{'name'};
/**
* This above statement will take care if the node string contain characters not permitted under PHP's naming convention (e.g. the hyphen) can be accomplished by encapsulating the element name within braces and the apostrophe.
*/
?>
More info is available here.
Hope it helps.

How do I loop nodes using NSXML on the Mac and change each node's text value

have been stuck on this for days now- How can I loop every node in an XML document and change the text value of the node.
For example go from this:
<root>
<node1>some text</node1>
<node2>
<node3>some more text</node3>
</node2>
</root>
to something like:
<root>
<node1>updated text</node1>
<node2>
<node3>updated text</node3>
</node2>
</root>
The code I have that doesn't work is:
NSArray *nodes = [xmlDoc nodesForXPath:#"//*"];
for (NSXMLElement *node in nodes) {
//In time a function call will go here to change the text:
NSString *newVal = #"updated text";
[node setStringValue:newVal];
}
Although it seems to loop ok when i check the contents of XMLDoc it then has this in it:
<root>
updated text
</root>
Please help if you can I have tried repeated google searches and am pulling my (already thinning) hair out - surely this should be fairly simple?!
Matt.
It's your xpath expression. //* selects all nodes in the document including the root node. So at some point in the iteration you are setting the string value of the root node which is apparently wiping out all its previous child nodes.
I'm not an expert in xpath, but something like:
/root//*
might do the trick except that node3 will get wiped out for the same reasons. If you look through The XPath tutorial there should be a way in there of selecting all text nodes.