Mac::PropertyList::SAX - work with Mac plists at a low level, fast


See Mac::PropertyList


Mac::PropertyList is useful, but very slow on large files because it does XML parsing itself, intead of handing it off to a dedicated parser. This module uses XML::SAX::ParserFactory to select a parser capable of doing the heavy lifting, reducing parsing time on large files by a factor of 30 or more.

This module does not replace Mac::PropertyList: it depends on it for some package definitions and plist printing routines. You should, however, be able to replace all use Mac::PropertyList lines with use Mac::PropertyList::SAX, without changing anything else, and notice an immediate improvement in performance on large input files.

Performance will depend largely on the parser that XML::SAX::ParserFactory selects for you. By default, XML::SAX::Expat is used; to change the parser used, set the environment variable MAC_PROPERTYLIST_SAX_PARSER to a value accepted by $XML::SAX::ParserPackage from XML::SAX::ParserFactory (or set $XML::SAX::ParserPackage directly).


Class scoped variables that control the packages settings.


Allows the XHTML encoding of the data to be turned off. Default = 1


A Perl character class definition containing the only characters to be XHTML encoded. See HTML::Entities::encode_entities for description of the $unsafe_chars parameter. Default = undef


Restores the old behavior of double encoding output data. Default = 0


Parser to use. Can also be set with environment variable MAC_PROPERTYLIST_SAX_PARSER. Default = "XML::SAX::Expat"


By default, no functions are exported. Specify individual functions to export as usual, or use the tags ':all', ':create', and ':parse' for the appropriate sets of functions (':create' includes the create* functions as well as plist_as_string; ':parse' includes the parse* functions).



See "parse_plist_file" in Mac::PropertyList


See "parse_plist_fh" in Mac::PropertyList


See "parse_plist" in Mac::PropertyList


An alias to parse_plist, provided for better regularity compared to Perl SAX.

create_from( HASH_REF | ARRAY_REF | STRING )

Dispatches to create_from_ref or create_from_string depending on the type of the argument.

create_from_ref( HASH_REF | ARRAY_REF )

Create a plist from an array or hash reference.

The values of the hash can be simple scalars or references. Hash and array references are handled recursively, and Mac::PropertyList objects are output correctly. All other scalars are treated as strings (use Mac::PropertyList objects to represent other types of scalars).

Returns a string representing the reference in serialized plist format.

create_from_hash( HASH_REF )

Provided for backward compatibility with Mac::PropertyList: aliases create_from_ref.

create_from_array( ARRAY_REF )

Provided for backward compatibility with Mac::PropertyList: aliases create_from_ref.

create_from_string( STRING )

Provided for backward compatibility with Mac::PropertyList: aliases Mac::PropertyList::create_from_string().

_escape( STRING )

Internal use only. Escapes illegal characters into XML entities.


Any sane XML parser you can find to use with this module will decode XHTML-encoded entities in the original property list; Mac::PropertyList doesn't touch them. Also, your XML parser may convert accented/special characters into '\x{ff}' sequences; these are preserved in their original encoding by Mac::PropertyList.

Before version 0.80 of this module, characters invalid in XML were not serialized properly from create_from_ref(); before version 0.82, they were not serialized properly in plist_as_string(). Thanks to Jon Connell for pointing out these problems.

Unlike Mac::PropertyList and old versions (< 0.60) of Mac::PropertyList::SAX, this module does not trim leading and trailing whitespace from plist elements. The difference in behavior is thought to be rarely noticeable; in any case, I believe this module's current behavior is the more correct. Any documentation that covers this problem would be appreciated.

The behavior of create_from_hash and create_from_array has changed: these functions (which are really just aliases to the new create_from_ref function) are now capable of recursively serializing complex data structures. That is: for inputs that Mac::PropertyList's create_from_* functions handled, the output should be the same, but this module supports inputs that Mac::PropertyList does not.

Before version 0.83, this module left the selection of a SAX-based parser entirely to the discretion of XML::SAX::ParserFactory. Unfortunately, it seems impossible to guarantee that the parser returned even supports XML (XML::SAX::RTF could be returned), so it has become necessary to select a parser by default: XML::SAX::Expat, which is now part of the dependencies of this module. If you know you will use another parser of a specific name, you can force installation without XML::SAX::Expat and always specify the parser you wish to use by setting $XML::SAX::ParserPackage or the MAC_PROPERTYLIST_SAX_PARSER environment variable (see "DESCRIPTION").

Before version 0.85, this module contained a bug that caused double encoding of special characters as X[HT]ML entities. Thanks to Bion Pohl and for reporting this issue and supplying a fixed version. The implementation of the $ENCODE_ENTITIES variable and the addition of the $ENCODE_UNSAFE_CHARS variable are also due to Bion Pohl and / or

Before version 0.86, this module did not handle binary plists. Now it delegates binary plists to Mac::PropertyList, but if used with filehandles, requires seekable streams (\*STDIN will work but only if it points to a seekable file, rather than a pipe).


Please contact the author with bug reports or feature requests.


Darren M. Kulp, <kulp @>


brian d foy, who created the Mac::PropertyList module whose tests were appropriated for this module.

Bion Pohl and, for bug report and patch submission.


Mac::PropertyList, the inspiration for this module.


Copyright (C) 2006-2022 by Darren Kulp

This program is free software under the terms of the Artistic License 2.0; see the accompanying LICENSE file for full terms.