How to read plist value by AppleScript?

Discussion in 'Mac Programming' started by mikezang, Aug 25, 2012.

  1. mikezang macrumors 6502a

    Joined:
    May 22, 2010
    Location:
    Tokyo, Japan
    #1
    I have a plist file as below, I want to get all value of "showName" and "videoURLString", how can I read it by AppleScript or bash easily? especially when there a lot of "dict" in plist file.

    Code:
    <?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>showName</key>
    * * <string>绝色武器</string>
    * * <key>subIndex</key>
    * * <string>0</string>
    * * <key>typeID</key>
    * * <string>1</string>
    * * <key>vid</key>
    * * <string>15669746</string>
    * * <key>videoURLString</key>
    * * <string>http://ip/file.txt</string>
    * </dict>
    </array>
    </plist>
    
     
  2. kryten2 macrumors 6502a

    Joined:
    Mar 17, 2012
    Location:
    Belgium
  3. mikezang thread starter macrumors 6502a

    Joined:
    May 22, 2010
    Location:
    Tokyo, Japan
    #4
    I tried code as below, but I got error, what can I do?
    Code:
    defaults read ~/Downloads.plist "showName"
    The error message is as below:
    Preference plist for {~/Downloads.plist : kCFPreferencesCurrentUser : kCFPreferencesAnyHost} was not a dictionary.
    2012-08-26 00:36:42.168 defaults[8969:707]
    The domain/default pair of (~Downloads.plist, showName) does not exist
     
  4. kryten2, Aug 25, 2012
    Last edited: Aug 25, 2012

    kryten2 macrumors 6502a

    Joined:
    Mar 17, 2012
    Location:
    Belgium
    #5
    I got the same error when using your plist. Perhaps it has a syntax error. When using PlistBuddy like chown33 said I get this :

    @chown33

    Thanks for the PlistBuddy tip.

    Edit after changing the plist to :

    Code:
    <?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">
    <dict>
    <key>showName</key>
    <string>绝色武器</string>
    <key>subIndex</key>
    <string>0</string>
    <key>typeID</key>
    <string>1</string>
    <key>vid</key>
    <string>15669746</string>
    <key>videoURLString</key>
    <string>http://ip/file.txt</string>
    </dict>
    </plist>
    The result is the second tumbnail.
     

    Attached Files:

  5. Red Menace macrumors 6502

    Red Menace

    Joined:
    May 29, 2011
    Location:
    Littleton, Colorado, USA
    #6
    If you are using AppleScriptObjC, you can also use NSArray's valueForKey: method, via either a Cocoa-AppleScript application or ASObjC Runner.
     
  6. mikezang, Aug 25, 2012
    Last edited: Aug 25, 2012

    mikezang thread starter macrumors 6502a

    Joined:
    May 22, 2010
    Location:
    Tokyo, Japan
    #7
    You can't remove Array tag, that is what I have to parse element.

    ----------

    I am not sure whyit Is so difficult to parse plist with array? it is so popular to be used in plist file....
     
  7. Red Menace macrumors 6502

    Red Menace

    Joined:
    May 29, 2011
    Location:
    Littleton, Colorado, USA
    #8
    It isn't all that difficult, I suppose it depends on exactly what you are doing and what you mean by "easily". Using System Events, you can loop through the dictionaries in the array (a general-purpose handler to get an individual item is about 18 lines of code), while using ASObjC Runner the statements can be simplified to one, and it takes a couple of statements using Cocoa methods to get all the values for a particular key.
     
  8. mikezang thread starter macrumors 6502a

    Joined:
    May 22, 2010
    Location:
    Tokyo, Japan
    #9
    Can you show me that 18 lines code?
    By the way, for AsObjC Runner, I have to install a application, so I thought 18 is better than 1:)
     
  9. Red Menace macrumors 6502

    Red Menace

    Joined:
    May 29, 2011
    Location:
    Littleton, Colorado, USA
    #10
    The following example uses a general-purpose handler that takes a list of items to define an element to get a value from:


    Code:
    on run -- example
    	set plistFile to (choose file) -- the plist file to use
    	set theKeys to {"showName", "videoURLString"} -- the keys to get values of
    	
    	set X to 1 -- begin with the first array item
    	set theResult to {} -- this will be the values of the keys of the array items
    	repeat -- forever, or at least until there is an error in getting an element
    		try -- group the results - in this example, a list of lists of the key values
    			set keyItems to {} -- this will be the values of the keys in the current array item
    			repeat with aKey in theKeys
    				set end of keyItems to (getPlistElement from {plistFile, X, aKey})
    			end repeat
    			set end of theResult to keyItems
    		on error errmess
    			log errmess
    			exit repeat
    		end try
    		set X to X + 1 -- the next array item
    	end repeat
    	
    	return theResult
    end run
    
    
    to getPlistElement from plistItems
    	(*
    	get the specified element from a simple plist structure by name or index
        	the number of items is not fixed, but must be at least 2 (the Plist file and a Plist element)
     		parameters:		plistItems [list] -
    							item 1 [varies]: the plist file path
    							item 2 [varies]: the plist element name or index (names are case sensitive)
    							item(s) 3+ [varies]: sub item(s)
    		returns [mixed]:	contents of the element
    	*)
    	try
    		if (count plistItems) is less than 2 then error "getPlistElement handler:  item list contains too few items"
    		tell application "System Events"
    			set thePlistElement to property list file ((first item of plistItems) as text) -- start at the root element
    			
    			repeat with anItem in rest of plistItems -- add on the sub items
    				set anItem to the contents of anItem
    				set thePlistElement to (get property list item anItem of thePlistElement)
    			end repeat
    			
    			return value of thePlistElement
    		end tell
    	on error errorMessage number errorNumber
    		log errorMessage
    		error "getPlistElement handler:  element not found (" & errorNumber & ")"
    	end try
    end getPlistElement
     
  10. mikezang, Aug 27, 2012
    Last edited: Aug 27, 2012

    mikezang thread starter macrumors 6502a

    Joined:
    May 22, 2010
    Location:
    Tokyo, Japan
  11. mikezang thread starter macrumors 6502a

    Joined:
    May 22, 2010
    Location:
    Tokyo, Japan
    #12
    Hi, can you show me a sample? I tried code as below, but with error message:
    "Print: Entry, "dict:0:showName", Does Not Exist"

    Code:
    /usr/libexec/PlistBuddy -c "Print dict:0:showName" "${downloadsplistfile}"
    
     
  12. mikezang thread starter macrumors 6502a

    Joined:
    May 22, 2010
    Location:
    Tokyo, Japan
    #13
    Well, I just got it with code as below by myself. anyway, thanks for you to tell me PlistBuddy:)
    Code:
    plistfile="${HOME}/Downloads.plist"
    
    showName="$(/usr/libexec/PlistBuddy -c "Print" "${plistfile}" | awk '/showName = /{print $3}' | nl)"
    videoURLString="$(/usr/libexec/PlistBuddy -c "Print" "${plistfile}" | awk '/videoURLString = /{print $3}' | nl)"
    
    printf "%s\n" "${showName[@]}"
    printf "%s\n" "${videoURLString[@]}"
    
     

Share This Page