thoellri's Journal
http://use.perl.org/~thoellri/journal/
thoellri's use Perl Journalen-ususe Perl; is Copyright 1998-2006, Chris Nandor. Stories, comments, journals, and other submissions posted on use Perl; are Copyright their respective owners.2012-01-25T02:47:41+00:00pudgepudge@perl.orgTechnologyhourly11970-01-01T00:00+00:00thoellri's Journalhttp://use.perl.org/images/topics/useperl.gif
http://use.perl.org/~thoellri/journal/
Foundation vs. Mac::Propertylist
http://use.perl.org/~thoellri/journal/25149?from=rss
<tt>I needed to access iPhoto's AlbumData.xml file in order to read my iPhoto database.<br><br>Mac::iPhoto did not work for me it always failed loading the xml-file (now I know why).<br><br>Mac::PropertyList would work after massaging the XML data before handing it of to plist_parse. However the solution was painfully slow. My 600KB AlbumData.xml file took more than 30 secs to load and parse on a Mac Mini.<br><br>So I looked into other ways to load the data from AlbumData.xml. Via PerlObjCBridge I implemented some code using NSPropertyListSerialization. I'm happy to report that the 30 secs have turned into 3 secs. That's better<nobr> <wbr></nobr>...<br><br>The data returned from plistToHash and loadiPhotoDB are different! There are some data types missing in the plistTraverse() sub!<br><br>--------------------------------------------------<br>use strict;<br>use Foundation;<br>use Mac::PropertyList;<br>use Time::HiRes qw{gettimeofday tv_interval};<br><br>use constant XML => qq{$ENV{HOME}/Pictures/iPhoto Library/AlbumData.xml};<br><br>my $t0 = [gettimeofday];<br>my $hash=plistToHash(XML);<br>my $elapsed = tv_interval($t0);<br>print "using plistToHash = $elapsed\n";<br>$t0 = [gettimeofday];<br>$hash=loadiPhotoDB(XML);<br>$elapsed = tv_interval($t0);<br>print "using Mac::PropertyList = $elapsed\n";<br><br>sub plistToHash {<br> my($filename)=@_;<br> my $data=NSData->dataWithContentsOfFile_($filename);<br> return undef unless($data);<br> my $plist=NSPropertyListSerialization->propertyListFromData_mutabilityOption_forma<nobr>t<wbr></nobr> _errorDescription_($data,0,undef,undef);<br> return undef unless($plist);<br> my %dict=();<br> return plistTraverse(\%dict,$plist,'dict',0);<br>}<br><br>sub plistTraverse {<br> my($dest,$src,$type,$depth)=@_;<br> my $e=($type eq 'dict')?$src->keyEnumerator():$src->objectEnumerator;<br> while(my $next = $e->nextObject()) {<br> last unless($$next);<br> my $obj=($type eq 'dict')?$src->objectForKey_($next):$next;<br> my $class=$obj->className->cString();<br> my $keyString=($type eq 'dict')?$next->cString:"";<br> if($class =~<nobr> <wbr></nobr>/dictionary$/i){<br> my %dict=();<br> my $sub=plistTraverse(\%dict,$obj,'dict',$depth+1);<br> if($type eq 'dict') {<br> $dest->{$keyString}=$sub;<br> }else{<br> push(@$dest,$sub);<br> }<br> }elsif($class =~<nobr> <wbr></nobr>/array$/i){<br> my @array=();<br> my $sub=plistTraverse(\@array,$obj,'array',$depth+1);<br> if($type eq 'dict') {<br> $dest->{$keyString}=$sub;<br> }else{<br> push(@$dest,$sub);<br> }<br> }elsif($class =~<nobr> <wbr></nobr>/string$/i){<br> if($type eq 'dict') {<br> $dest->{$keyString}=$obj->cString;<br> } else {<br> push(@$dest,$obj->cString);<br> }<br> }elsif($class =~<nobr> <wbr></nobr>/number$/i){<br> if($type eq 'dict') {<br> $dest->{$keyString}=$obj->doubleValue;<br> } else {<br> push(@$dest,$obj->doubleValue);<br> }<br> }elsif($class =~<nobr> <wbr></nobr>/boolean$/i){<br> if($type eq 'dict') {<br> $dest->{$keyString}=($obj->boolValue eq 'YES')?1:0;<br> } else {<br> push(@$dest,($obj->boolValue eq 'YES')?1:0);<br> }<br> } else {<br> print STDERR "**** unhandled class: $class\n";<br> }<br> }<br> return $dest;<br>}<br><br>sub loadiPhotoDB {<br> my($catalogPath)=@_;<br> my $xml;<br> open(CATALOG, $catalogPath) || return undef;<br> {local $/=undef;$xml=<CATALOG>;}<br> close(CATALOG);<br><br> # Mac::PropertyList is pretty strict about what it expects to<br> # see in the XML file. We are trimming the file before handing<br> # it off to parse_plist<br> $xml =~ s{^.*<plist\s*.*?>\s*}{}s;<br> $xml =~ s{\s*</plist\s*.*?>\s*\z}{}s;<br><br> my $dict=Mac::PropertyList::parse_plist($xml);<br> return $dict;<br>}<br><br></tt>thoellri2005-06-11T12:20:35+00:00journal