Cocoa replacing XMLElements - objective-c

If I have the following example code:
NSXMLDocument* doc = [[NSXMLDocument alloc] initWithContentsOfURL: [NSURL fileURLWithPath:#"file2.xml"] options:0 error:NULL];
NSXMLElement* root = [doc rootElement];
NSArray* objectElements = [root nodesForXPath:#"//object" error:nil];
NSLog (#"doc - %#", doc);
NSXMLElement *c1 = [objectElements objectAtIndex:0];
NSLog (#"c1 --> %#",[c1 stringValue]);
//creating new element
NSXMLElement *c2 = [NSXMLElement elementWithName:#"value" stringValue:#"object new node"];
[c1 replaceChildAtIndex:0 withNode:c2];
NSLog (#"New doc - %#", doc);
I am trying to get an XML element and change its value to another (c2). The problem is that with the new node replacing, I am getting the element name as well inserted into the XML Document.
So, if I have
<element>old value</element>,
I am now getting:
<element><newElement>new value</newElement></element>
How can I program the code so that
<newElement></newElement>
do not get displayed? Thanks
P.S. Even simpler way of explaining:
Basically, I want to replace an Element with another element. So from
<e1>data1</e1>
I want to have
<e2>data 2</e2>
in its place.

I may be misunderstanding the question but it sounds like you are just trying to make the first element have the second ones attributes? Try something like:
- (void) method {
NSArry* attrs = [c2 attributes];
[c1 setAttributes: attrs];
}
Hope that helps.

Related

Using a String representing the name of a variable to set the variable

This is a basic example that I know can be simplified, but for testing sake, I would like to do this in such a way. I want to set a variable based on an appending string (the variables "cam0" and "pos1" are already declared in the class). The appending string would essentially be an index, and i would iterate through a loop to assign cameras (cam0, cam1..) to different positions (pos0, pos1..).
cam0 is defined as an UIImageView
pos1 is defined as a CGRect
This works for a NSString Variable named coverIndex:
NSString* text = [[NSString alloc] initWithString:#""];
NSLog(#"%#",(NSString *)[self performSelector:NSSelectorFromString([text stringByAppendingString:#"coverIndex"])]);
The correct string that I set for coverIndex was logged to the Console.
Now back to my UIImageView and CGRect. I want this to work.
NSString* camText = [[NSString alloc] initWithString:#"cam"];
NSString* posText = [[NSString alloc] initWithString:#"pos"];
[(UIImageView *)[self performSelector:NSSelectorFromString([camText stringByAppendingString:#"0"])] setFrame:(CGRect)[self performSelector:NSSelectorFromString([posText stringByAppendingString:#"1"])]];
My error is "Conversion to non-scalar type requested"
This is the only way I found to do this sort of thing (and get the NSLog to work), but I still believe there is an easier way.
Thank you so much for any help :)
Use KVC, it's an amazing piece of technology that will do just what you want:
for (int index = 0; index < LIMIT; index++) {
NSString *posName = [NSString stringWithFormat:#"pos%d", index];
CGRect pos = [[self valueForKey:posName] CGRectValue];
NSString *camName = [NSString stringWithFormat:#"cam%d", index];
UIImageView *cam = [self valueForKey:camName];
cam.frame = pos;
}
One way you can do this would be to create your cameras in a dictionary and use those special NSStrings to key in to it. Like,
NSMutableDictionary *myCams;
myCams = [[myCams alloc] init];
[myCams addObject:YOUR_CAM0_OBJECT_HERE forKey:#"cam[0]"];
[myCams addObject:YOUR_CAM1_OBJECT_HERE forKey:#"cam[1]"];
NSString camString = #"cam[0]"; // you'd build your string here like you do now
id theCamYouWant = [myCams objectForKey:camString];

write html content to NSString and display on iphone

i have a webveiw where i can show small html value but i have a issue
if is do this
NSString *HTMLData =#"<h3><span style=font-family:Helvetica-Bold > <strong> Information</strong> </span></h3>";
HTMLData= [HTMLData stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
[web loadHTMLString:HTMLData baseURL:nil];
then its wokring fine
but if my NSString has a break line lets say
NSString *HTMLData =#"<h3><span style=font-family:Helvetica-Bold >
<strong> Information</strong>
</span></h3>";
then i am getting error how to avoid this error???
my error is missing terminator charcter
To break long NSStrings across multiple lines, you need to put double quotes at the end and beginning of each line:
NSString *HTMLData =#"<h3><span style=font-family:Helvetica-Bold >"
"<strong> Information</strong>"
"</span></h3>";
Edit:
An example with NSMutableString:
NSMutableString *HTMLData = [[NSMutableString alloc] initWithCapacity:100];
[HTMLData appendString:#"<h3><span style=font-family:Helvetica-Bold >"];
[HTMLData appendString:#"<strong> Information</strong>"];
[HTMLData appendString:#"</span></h3>"];
//more appends...
//do something with HTMLData here
[HTMLData release];
The initWithCapacity just tells how many characters to allocate space for initially (it's not a limit).
NSMutableString also has the appendFormat: method which works like stringWithFormat:.
One solution for this could be simply write your HTML as an String.
and show the string as an Attributed String for Label.
let htmlText = "<p>etc</p>"
if let htmlData = htmlText.dataUsingEncoding(NSUnicodeStringEncoding) {
do {
someLabel.attributedText = try NSAttributedString(data: htmlData,
options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType],
documentAttributes: nil)
} catch let e as NSError {
print("Couldn't translate \(htmlText): \(e.localizedDescription) ")
}
}
reference : How to show an HTML string on a UILabel

Using NSXMLElement to add a tag in the middle of a block of text

I need to create an XML document with the following type of format.
<Para>
This is some text about <someMethod> that you need to know about.
</Para>
I'm having no issues with general XML generation, but this one aspect is giving me some issues.
One approach is to make a mutable copy of the stringValue of the para node and then insert your tags around the "someMethod" text. Create a new NSXMLNode from that using -[NSXMLNode initWithXMLString:error:] and replace the old NSXMLNode with the new NSXMLNode. That's probably shorter, but it requires some string manipulation.
If you know the para node is a single run of text, then you can use this category on NSXMLNode I just wrote which seems a bit more verbose to me than what I described. Depends on what your needs are and how much you like messing around with NSMutableStrings. :)
#implementation NSXMLElement (ElementSplitting)
- (void)splitTextAtRangeInStringValue:(NSRange)newNodeRange withElement:(NSString *)element {
/* This is pretty simplistic; it assumes that you're attempting to split an element node (the receiver) with a single stringValue. If you need to do anything more complicated, you'll have to do some more work. For this limited example, we need three new nodes(!):
1. One new text node for the first part of the original string
2. One new element node with a stringValue of the annotated part of the string
3. One new text node for the tail part of the original string
An alternate approach is to use -[NSXMLNode initWithXMLString:error:] after making a mutable copy of the string and modifying that string with the new markup you want.
*/
NSXMLNode *prefaceTextNode = [[NSXMLNode alloc] initWithKind:NSXMLTextKind];
NSXMLElement *elementNode = [[NSXMLNode alloc] initWithKind:NSXMLElementKind];
NSXMLNode *suffixTextNode = [[NSXMLNode alloc] initWithKind:NSXMLTextKind];
NSString *fullStringValue = [self stringValue];
NSString *prefaceString = [fullStringValue substringToIndex:newNodeRange.location];
NSString *newElementString = [fullStringValue substringWithRange:newNodeRange];
NSString *suffixString = [fullStringValue substringFromIndex:newNodeRange.location + newNodeRange.length];
[prefaceTextNode setStringValue:prefaceString];
[elementNode setName:element];
[elementNode setStringValue:newElementString];
[suffixTextNode setStringValue:suffixString];
NSArray *newChildren = [[NSArray alloc] initWithObjects:prefaceTextNode, elementNode, suffixTextNode, nil];
for (id item in newChildren) { [item release]; } // The array owns these now.
[self setChildren:newChildren];
[newChildren release];
}
#end
...and here's a small example:
NSString *xml_string = #"<para>This is some text about something.</para>";
NSError *xml_error = nil;
NSXMLDocument *doc = [[NSXMLDocument alloc] initWithXMLString:xml_string options:NSXMLNodeOptionsNone error:&xml_error];
NSXMLElement *node = [[doc children] objectAtIndex:0];
NSString *childString = [node stringValue];
NSRange splitRange = [childString rangeOfString:#"text about"];
[node splitTextAtRangeInStringValue:splitRange withElement:#"codeVoice"];
If <someMethod> is actually an element, then you need to create a NSXMLNode of kind NSXMLTextKind (via initWithKind:), create your <someMethod> node, and create another text node, then add all three in order as children to your <Para> node. The key is creating the two text parts as separate nodes.
After rereading the question, I'm thinking maybe <someMethod> wasn't intended to be a node, but should have been text? If so, it's just an escaping problem (< | >) but I'm guessing that it's not something that simple, considering who you are. :)

TouchXML, get text value of node objective-c

I've looked all over the web but just can't figure out how to get the text from a node in Objective-C. I'm using TouchXML and I am getting my node list. I want the title text from a node, but instead I get a node object. My code is:
resultNodes = [xmlParser nodesForXPath:#"SearchResults/SearchResult" error:&err];
for (CXMLElement *resultElement in resultNodes) {
        
NSString *value = [resultElement elementsForName:#"Title"];
}
If I log the value to the console I get:
<CXMLElement 0x3994b10 [0x39732a0] Title <Title HtmlEncoded="true">test question</Title>>
I want the text, i.e test question instead. I am banging my head against a brick wall here.
Since there should atleast one element in "resultElement" for the given value"Title", you can probably access it by adding following line of code:
NSString *value = [[[resultElement elementsForName:#"Title"] objectAtIndex:0] stringValue];
Try:
NSString *value = [[resultElement elementsForName:#"Title"] getStringValue];

How to Extract AppleScript Data from a NSAppleEventDescriptor in Cocoa and Parse it

What I'm doing is executing an AppleScript inside of Cocoa. It returns some data as a NSAppleEventDescriptor, which NSLog() prints like so:
<NSAppleEventDescriptor: 'obj '{ 'form':'name', 'want':'dskp', 'seld':'utxt'("69671872"), 'from':'null'() }>
I want to take that data and turn it into a NSDictionary or NSArray, or something useful so I can extract stuff from it (specifically I'm after the field holding the "69671872" number). It appears to be an array of some sort, but my knowledge with Apple Events is fairly limited. Any idea on how to do this?
Here's the source creating the above data:
NSString *appleScriptSource = [NSString stringWithFormat:#"tell application\"System Events\"\n return desktop 1\n end tell"];
NSDictionary *anError;
NSAppleScript *aScript = [[NSAppleScript alloc] initWithSource:appleScriptSource];
NSAppleEventDescriptor *aDescriptor = [aScript executeAndReturnError:&anError];
NSLog (#"%#", aDescriptor);
[aScript release];
Thanks in advance for any help! :)
That's a record, not a list. Try descriptorForKeyword:, passing the constant matching the four-character code you want. (The constants are declared in the Apple Events headers.)
[[aDescriptor descriptorForKeyword:keyAEKeyData] stringValue]
I was unable to get Peter Hosey's solution to work on my AppleScript list wrapped as a NSAppleEventDescriptor. Instead, I came upon the following solution that coerces the list to an ObjC array:
NSAppleEventDescriptor *listDescriptor = [result coerceToDescriptorType:typeAEList];
NSMutableArray *thisArray = [[NSMutableArray alloc] init];
for (NSInteger i = 1; i <= [listDescriptor numberOfItems]; ++i) {
NSAppleEventDescriptor *stringDescriptor = [listDescriptor descriptorAtIndex:i];
[thisArray addObject: stringDescriptor.stringValue];
}
NSLog(#"array result: %#", thisArray);