Ambulare
Ambulare

Reputation: 933

How can I parse the contents of text in a variable formatted as a plist using applescript?

I would like to extract some details of the installed apps on an Apple Mac. I thought that the most portable way to run this on a bunch of Macs without any extra dependencies was to use Applescript.

I can get a variable containing the installed apps in plist format by running:

set theAppsList to do shell script "system_profiler SPApplicationsDataType -xml"

but I can't find a way to tell Applescript to parse this text as a plist. All the documented plist examples show the passing of a filepath to Applescript in the form:

tell application "System Events" to tell property list file thePropertyListFilePath to ....

but how can I process the raw plist text I receive from the shell script as a plist object? Is there some equivalent of the pseudocode:

myPlist = new property list (theAppsList)

that would create a new plist object in memory?

Upvotes: 0

Views: 349

Answers (1)

CJK
CJK

Reputation: 6102

Treat the data as XML data, which AppleScript can parse as text data stored in a variable. Here's a portion of the text data returned on my system when I ran your do shell script line:

    <?xml version=\"1.0\" encoding=\"UTF-8\"?>
    <!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">
    <plist version=\"1.0\">
    <array>
        <dict>
            <key>_SPCommandLineArguments</key>
                    .
                    .
                    .
            <key>_items</key>
            <array> --> ① 
                <dict> --> ② 
                    <key>_name</key>
                    <string>Little Snitch Software Update</string> --> ③ 
                    .
                    .
                    .

The following AppleScript isolates the XML elements labelled ① and ② and stores their data as lists from which, ultimately, information about each application can be retrieved (e.g. the element labelled ③ denoting the first application's name):

    tell application "System Events"
        -- Creates a new XML data object and stores it in memory
        if not (exists XML data "AppData") then ¬
            set XMLAppData to make new XML data ¬
                with properties ¬
                {name:"AppData", text:theAppsList}

        -- array element labelled ① 
        tell XML data "AppData" to ¬
            set AppArray to item 2 of (XML elements of ¬
                XML element "dict" of XML element "array" of ¬
                XML element "plist" whose name is "array")

        -- dict element labelled ② 
        set AppsDataArray to every XML element in AppArray whose name is "dict"
        -- The number of applications installed
        set n to number of items in AppsDataArray

        -- Retrieving ③ from the AppsDataArray list
        -- (the name of the first application)
        get value of XML element "string" of item 1 in AppsDataArray
    end tell

I believe XML data objects disappear from memory after about 5 minutes of idle time. Otherwise, you can manually delete them using delete XML data "AppData" or delete every XML data.

Upvotes: 2

Related Questions