The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Mac::PropertyList - work with Mac plists at a low level

SYNOPSIS

        use Mac::PropertyList;

        my $data  = parse_plist( $text );

        my $text  = plist_as_string( $data );

        my $plist = create_from_hash( \%hash );

DESCRIPTION

This module is a low-level interface to the Mac OS X Property List (plist) format. You probably shouldn't use this in applications---build interfaces on top of this so you don't have to put all the heinous multi-level hash stuff where people can see it.

You can parse a plist file and get back a data structure. You can take that data structure and get back the plist as XML. If you want to change the structure inbetween that's your business. :)

The Property List format

The MacOS X Property List format is simple XML. You can read the DTD to get the details.

        http://www.apple.com/DTDs/PropertyList-1.0.dtd

One big problem exists---its dict type uses a flat structure to list keys and values so that values are only associated with their keys by their position in the file rather than by the structure of the DTD. This problem is the major design hinderance in this module. A smart XML format would have made things much easier.

If the parse_plist encounters an empty key tag in a dict structure (i.e. <key></key> ) the function dies. This is a misfeature which I want to correct in future versions.

The Mac::PropertyList data structure

A plist can have one or more of any of the plist objects, and we have to remember the type of thing so we can go back to the XML format. Perl treats numbers and strings the same, but the plist format doesn't.

Therefore, everything Mac::PropertyList creates is an anonymous hash. The key "type" is the plist object type, and the value "value" is the data.

The hash for a string object looks like

        {
        type  => 'string',
        value => 'this is the string'
        }

The structure for the date, data, integer, float, and real look the same.

The plist objects true and false are wierd since in the XML they are empty elements, but in this data structure Mac::Property list pretends they are not so it can avoid a special case.

        {
        type  => 'true',
        value => 'true'
        }

The hash for a plist array object looks the same, but its value is an anonymous array which holds more plist objects (which are in turn hashes).

        {
        type  => 'array',
        value => [
                { type => integer, value => 1 },
                { type => string,  value => 'Foo' }
                ]
        }

The hash for a plist dict object is similar. The values of the keys are in turn plist objects again.

        {
        type  => 'dict',
        value => {
                "Bar" => { type => string,  value => 'Foo' }
                }
        }

From here you can make any combination of the above structures. I do not intend that you should have to know any of this at the application level. People should create another layer on top of this to provide a simple interface to a particular plist file.

Run a small script against your favorite plist file then dump the results with Data::Dumper. That's what the real deal looks like.

FUNCTIONS

parse_plist( TEXT )

Parse the XML plist in TEXT and return the Mac::PropertyList data structure.

create_from_hash( HASH_REF )

Create a plist dictionary from the hash reference.

The values of the hash can only be simple scalars---not references. Reference values are silently ignored.

Returns a string representing the hash in the plist format.

SOURCE AVAILABILITY

This source is part of a SourceForge project which always has the latest sources in CVS, as well as all of the previous releases.

        https://sourceforge.net/projects/brian-d-foy/

If, for some reason, I disappear from the world, one of the other members of the project can shepherd this module appropriately.

CREDITS

Thanks to Chris Nandor for general Mac kung fu and Chad Walker for help figuring out the recursion for nested structures.

TO DO

* actually test the write_* stuff

* the read_dict method dies() if the key is not defined. i do not like to die from functions.

* do this from a filehandle or a scalar reference instead of a scalar + generate closures to handle the work.

AUTHOR

brian d foy, <bdfoy@cpan.org>

SEE ALSO

http://www.apple.com/DTDs/PropertyList-1.0.dtd