PDA

View Full Version : XML file handling help




A@ron
Feb 20, 2007, 10:46 PM
First off, thank you to anyone that can help I am really just a cocoa novice on a mission to write something useful :)

Background:
I am working on a preference pane front end to TivoMono (http://sourceforge.net/projects/tivodotnet/) which simply can put files on my tivo and transcode them on the fly for it.
I only need this preferance pane to really perform 4 different functions:
1) start the terminal process with mono Tivomono.exe --nodetails --noterminal Done
2) be able to stop the process Done uses pkill and works
3) read the settings.xml that TivoMono.exe reads to configure itself and set the gui buttons/drop downs to reflect the current settings.

XML File Example
<TiVoMono>
<Installpath>/TivoMono/</Installpath>
<FFMpeg_Path>/TivoMono/ffmpeg</FFMpeg_Path>
<FFMpeg_Aspect>4:3</FFMpeg_Aspect>
<FFMpeg_VideoBitRate>2048</FFMpeg_VideoBitRate>
<FFMpeg_FrameRate>24</FFMpeg_FrameRate>
<FFMpeg_AudioBitRate>128</FFMpeg_AudioBitRate>
<FFMpeg_AudioSampleRate>48000</FFMpeg_AudioSampleRate>
<FFMpeg_RestrictAudioSampleRate>false</FFMpeg_RestrictAudioSampleRate>
<FFMpeg_AudioCodec>mp2</FFMpeg_AudioCodec>
<FFMpeg_AudioChannels>2</FFMpeg_AudioChannels>
<FFMpeg_RestrictAudioChannels>true</FFMpeg_RestrictAudioChannels>
<FFMpeg_AudioSyncSamples>1</FFMpeg_AudioSyncSamples>
<FFMpeg_UseAsync>false</FFMpeg_UseAsync>
<Directory>/Volumes/HD2/TiVoNet/</Directory>
<AllowedExtensions>.3g2,.3gp,.4xm,.mtv,.roq,.aac,.ac3,.adts,.aiff,.alaw,.amr,.asf,.au,.avi,.avs,.crc,.daud,.dsicin,.dts ,.dv,.dvd,.ea,.ffm,.flic,.flv,.gif,.gxf,.h261,.h263,.h264,.idcin,.ipmovie,.m4v,.matroska,.mjpeg,.mm, .mmf,.mov,.mp4,.m4a,.3gp,.mp2,.mp3,.mp4,.mpeg,.mpeg1video,.mpeg2video,.mpegts,.mpegvideo,.mpjpeg,.mu law,.mxf,.nsv,.nuv,.ogg,.psp,.psxstr,.rawvideo,.rm,.s16be,.s16le,.s8,.shn,.smk,.sol,.svcd,.swf,.tier texseq,.tta,.u16be,.u16le,.u8,.vcd,.vmd,.vob,.voc,.wav,.wc3movie,.wsaud,.wsvqa,.wv,.mpg</AllowedExtensions>
<UUID>190C7D52-C6F8-4D3C-A5FE-3D1710DFB898</UUID>
</TiVoMono>

4) If a save settings button is pressed then the preference pane needs to remake the settings.xml and replace the old one, kill the process and restart it.

What I need help with:
I am having a heck of a time opening this XML file properly and getting it to do what it needs to do. If anyone could get me pointed in the right direction that would be greatly appreciated. I've tried to read up on NSXML but examples are lacking unfortunately.

Here is my code so far if it helps:
homepage.mac.com/bedelman/TivoPref.zip (http://homepage.mac.com/bedelman/TivoPref.zip)

Thank you!



kainjow
Feb 21, 2007, 01:28 PM
I'm too lazy to look through your project.. mind putting the XML sample code up? If the XML isn't valid, NSXMLDocument will return nil and an error.

A@ron
Feb 21, 2007, 06:38 PM
NSXMLDocument *settingsXML;
NSString *path = @"/TivoMono/settings.xml";
NSURL *settingsURL = [NSURL fileURLWithPath:path];
if (!settingsURL) {
NSLog(@"Can't Create an URL from file %@.", path);
return;
}
settingsXML = [[NSXMLDocument alloc] initWithContentsOfURL:settingsURL];

I get an error in console:
2007-02-20 22:47:30.055 System Preferences[2093] *** -[NSXMLDocument initWithContentsOfURL:]: selector not recognized [self = 0x3be9e0]
2007-02-20 22:47:30.055 System Preferences[2093] *** NSRunLoop ignoring exception '*** -[NSXMLDocument initWithContentsOfURL:]: selector not recognized [self = 0x3be9e0]' that raised during posting of delayed perform with target 352e60 and selector 'setCurrentPreference:'

kainjow
Feb 21, 2007, 06:56 PM
missing a part:

- (id)initWithContentsOfURL:(NSURL *)url options:(unsigned int)mask error:(NSError **)error

A@ron
Feb 21, 2007, 08:54 PM
thanks for the tip unfortunately it's not quite clear to me what I've got to do. This might take too much hand holding for you to really help me much since I know you are quite busy. :(
I'll keep scouring google to see if I can't find more info but it seems quite sparse.

kainjow
Feb 21, 2007, 09:03 PM
Try:

settingsXML = [[NSXMLDocument alloc] initWithContentsOfURL:settingsURL
options:0 error:nil];

A@ron
Feb 21, 2007, 09:54 PM
damn you're good! Looks like it is reading the XML correctly. I am now trying to pull out the info of the XML. I have it reading an element in the XML with the following code:
NSXMLElement *Installpath;
NSXMLDocument *settingsXML;
NSString *path = @"/TivoMono/settings.xml";
NSURL *settingsURL = [NSURL fileURLWithPath:path];
if (!settingsURL) {
NSLog(@"Can't Create an URL from file %@.", path);
return;
}
settingsXML = [[NSXMLDocument alloc] initWithContentsOfURL:settingsURL
options:0 error:nil];
NSArray *nodes = [settingsXML nodesForXPath:@"./TiVoMono/FFMpeg_Path" error:nil];
Installpath = [nodes objectAtIndex:0];
[TestText setStringValue:Installpath];

The XML data I want returned is /TivoMono/ffmpeg
The TestText Output is: <FFMpeg_Path>/TivoMono/ffmpeg</FFMpeg_Path>
Any quick way to get the format looking the way I need it to?

lazydog
Feb 22, 2007, 03:40 AM
Don't know if this is of any help but you can also use the Core Foundation stuff for handling XML. The difference being that it is a C api which you might prefer. It's pretty easy to use once you have created a CFXMLTreeRef. For example, to create one from a string:-


NSData* xmlData = [ sourceStr dataUsingEncoding: NSNonLossyASCIIStringEncoding ] ;
CFXMLTreeRef tree = CFXMLTreeCreateFromData( kCFAllocatorDefault, (CFDataRef) xmlData, NULL, kCFXMLParserSkipWhitespace, kCFXMLNodeCurrentVersion ) ;


Once you've got a CFXMLTreeRef you just use C function calls to walk the XML tree and extract the data you want.

b e n

kainjow
Feb 22, 2007, 08:19 AM
The CFXML functions are not good though. They don't automatically handle entities and other annoying things. If you are targeting 10.4+, then use NSXML.

caveman_uk
Feb 22, 2007, 09:21 AM
The TestText Output is: <FFMpeg_Path>/TivoMono/ffmpeg</FFMpeg_Path>
Any quick way to get the format looking the way I need it to?
It took me ages to figure out how to get pretty XML output. The trick is

NSString* xmlOutput=[xmlDoc XMLStringWithOptions:NSXMLNodePrettyPrint];

where xmlDoc is an NSXMLDocument

EDIT: Nevermind....I just answered the wrong question.

EDIT2: You need to look at the NSXMLNode's objectValue to get what you want out of each node in your array

kainjow
Feb 22, 2007, 10:07 AM
damn you're good! Looks like it is reading the XML correctly. I am now trying to pull out the info of the XML. I have it reading an element in the XML with the following code:
NSXMLElement *Installpath;
NSXMLDocument *settingsXML;
NSString *path = @"/TivoMono/settings.xml";
NSURL *settingsURL = [NSURL fileURLWithPath:path];
if (!settingsURL) {
NSLog(@"Can't Create an URL from file %@.", path);
return;
}
settingsXML = [[NSXMLDocument alloc] initWithContentsOfURL:settingsURL
options:0 error:nil];
NSArray *nodes = [settingsXML nodesForXPath:@"./TiVoMono/FFMpeg_Path" error:nil];
Installpath = [nodes objectAtIndex:0];
[TestText setStringValue:Installpath];

The XML data I want returned is /TivoMono/ffmpeg
The TestText Output is: <FFMpeg_Path>/TivoMono/ffmpeg</FFMpeg_Path>
Any quick way to get the format looking the way I need it to?

Installpath is not an NSString. So you need to use:
[TestText setStringValue:[Installpath stringValue]];
To extract the NSString value from the XML element.

A@ron
Feb 25, 2007, 12:12 PM
cool. that all works :)

I've been trying to do some if statements but I am unable to get the casting right. I am trying to do something like the following:

if (valueFromXML == 128) {
//DoSomething
NSBeep();
}


I've tried a few combinations of ' and " and @ and looking online on how to cast this pointer into an int so this if statement will work to no avail.

I am so going to be owing someone some beer here by the time I learn Cocoa well.

A@ron
Mar 1, 2007, 09:39 PM
Still trying to get this working...
I would think this would work but it does not.
NSArray *audioCodecNodes = [settingsXML nodesForXPath:@"./TiVoMono/FFMpeg_AudioCodec" error:nil];
[audioCodecText setStringValue:[[audioCodecNodes objectAtIndex:0] stringValue]];
if ([(NSString *)audioCodecText isEqualToString:@"mp2"]==YES){
NSBeep();
}

the audioCodecText box in the UI shows mp2 in it which it is reading from the XML.

caveman_uk
Mar 2, 2007, 03:37 AM
cool. that all works :)

I've been trying to do some if statements but I am unable to get the casting right. I am trying to do something like the following:

if (valueFromXML == 128) {
//DoSomething
NSBeep();
}


I've tried a few combinations of ' and " and @ and looking online on how to cast this pointer into an int so this if statement will work to no avail.

I am so going to be owing someone some beer here by the time I learn Cocoa well.
[objectName intValue]