For one of my latest scripting projects at work I needed AppleScript to quickly parse a small XML file for certain informations.
As you know, there are already wonderful scripting additions available for this task, like the XML suite from Satimage or the XSLT Tools from Late Night Software, but unfortunately my script was supposed to work out of the box on every Mac in the company and so I couldn’t use them, as scripting additions need to be installed first.
What to do? Well, finally I wrote my own little and very simple foundation tool, which enables AppleScript to execute XPath expressions against an XML document using the excellent NSXMLNode class provided by Apple. The small tool can be included with the script/application bundle and there is no need to install a scripting addition first.
I know that asxpath might only be of minor interest for other people, but it works just fine and flawless in our project and so I decided to publish it here
asxpath requires Mac OS X 10.4 or later and was successfully tested on several Intel and Power-PC based Macs.
In case you want to adjust asxpath to your very own requirements I invite you to take a look at the most simple source code.
To test-drive asxpath on your fine Mac I wrote some sample code which utilizes asxpath to search the iTunes Music Library XML file for tracks of a certain artist. The demo assumes that you put asxpath on your desktop:
property mytitle : "asxpath demo"
-- I am searching the iTunes Music Library XML files for tracks by Steve Martin
-- using the asxpath command line tool
on run
try
-- asking the user to provide an artist name
set artist to my askforartist()
if artist is missing value then
return
end if
-- path to the asxpath foundation tool (assuming that it is loacted on the desktop)
set foundtoolpath to quoted form of POSIX path of ((path to desktop as text) & "asxpath")
-- path to the iTunes Music Library XML file
set xmllibrarypath to quoted form of POSIX path of ((path to music folder as text) & "iTunes:iTunes Music Library.xml")
-- an XPath expression searching for tracks by Steve Martin (you might want to adjust this)
set xpathexpression to quoted form of ("//string[preceding-sibling::key[1] = \"Name\" and following-sibling::string = \"" & artist & "\"]/text()")
-- setting the delimiter which separates the results from each other
-- you don't need to set it, it is optional, because asxpath uses "..." as the default delimiter
set delim to "@@@"
-- executing the command line tool
set command to foundtoolpath & " -file " & xmllibrarypath & " -xpath " & xpathexpression & " -delim " & delim
-- depeding on the size of your iTunes library, this may take some seconds...
-- remember, it's just a demo :-)
set output to do shell script command
-- splitting the output into usable reults
set tracknames to my gettxtitems(return & delim & return, output)
-- displaying the results
choose from list tracknames with prompt "All tracks in iTunes from " & artist & ":" with title mytitle
-- returns the following list on my Mac for artist 'Steve Martin':
-- {"I'm Feelin' It", "Philosophy / Religion / College / Language (Album Version)",
-- "Creativity In Action / I'm In the Mood for Love", "A Wild and Crazy Guy",
-- "A Charitable Kind of Guy", "An Exposé", "Cat Handcuffs", "You Naive Americans",
-- "My Real Name", "King Tut"}
on error errmsg number errnum
if errnum is not equal to -128 then
my dsperrmsg(errmsg, errnum)
end if
end try
end run
-- I am asking the user to provide an artist name
on askforartist()
try
tell me
activate
display dialog "I want to search iTunes for tracks by artist:" default answer "Steve Martin" buttons {"Cancel", "OK"} default button 2 with icon note with title mytitle
set dlgresult to result
end tell
on error
return missing value
end try
set usrinput to text returned of dlgresult
if usrinput is "" then
my askforartist()
else
return usrinput
end if
end askforartist
-- I am returning the text items of a text separated by the given delimiter
on gettxtitems(delim, txt)
set olddelims to AppleScript's text item delimiters
set AppleScript's text item delimiters to {delim}
set txtitems to text items of txt
set AppleScript's text item delimiters to olddelims
return txtitems
end gettxtitems
on dsperrmsg(errmsg, errnum)
tell me
activate
display dialog "Sorry, an error occured:" & return & return & errmsg & return & "(" & errnum & ")" buttons {"OK"} default button 1 with icon stop with title mytitle
end tell
end dsperrmsg
Happy Scripting!