So I have a wrinkle on the existing discussions within the other parts of the board regarding using AS and Automator to customize the System Profiler output.
I have a few thousand System Profiler Reports that are saved as “Basic” (as opposed to Mini or Full) reports. My goal, eventually, is match discrete elements from the reports to their respective machine histories in Filemaker. I am working my way through the problem slowly and trying different approaches to getting the data out of the .spx files.
So, using Automator to open selected files using Open Finder Items:Application:System Profile works to open the files, but I haven’t worked out how to save the output as plain text files. I’ve tried passing the output to an Applescript workflow, but I can’t seem to get the script syntax right to save the output as text.
I’d also like to only save some of the report, particularly the SPHardwareDataType, SPMemoryDataType, etc etc. Is there a way to operate on a file in Automator that’s passed through from the above example? It is possible in the System Profile workflow action and I know that you can invoke a shell script via AS to do this but, it’s only on the local machine, not a specified file or group of files.
TIA for any ideas on how to proceed
Regards,
Browser: Safari 419.3
Operating System: Mac OS X (10.4)
AppleScript has a built-in function to parse XML-files, but it’s not very fast (this script takes about 10 sec on my machine).
Anyway, here is a script to extract your requested data from a .spx file (which is actually a .xml file)
It shouldn’t be a problem to put it into an Automator action
BTW: I’s very much easier when you save the reports as plain text
set XMLfile to ((path to desktop) as string) & "G5-dual.spx"
set {fName, fDate} to {name, creation date} of (info for alias XMLfile)
set a to text 1 thru ((offset of "." in fName) - 1) of fName & " " & short date string of fDate & " " & time string of fDate & return & return
tell application "System Events"
tell XML file XMLfile
set ParamList to value of XML element 2 of XML elements of XML element 1 of XML element 1 of contents
repeat with i from 1 to count ParamList
if item i of ParamList is "SPHardwareDataType" then
set SPH to i
else if item i of ParamList is "SPMemoryDataType" then
set SPM to i
exit repeat
end if
end repeat
tell XML element 1 of XML element 6 of XML element SPH of XML element 1 of XML element 1 of contents
set a to a & "Hardware Overview:" & return & return
repeat with i from 3 to (count XML elements) by 2
set a to a & value of XML element i & ": "
set a to a & value of XML element (i + 1) & return
end repeat
set a to a & return & return & return
end tell
tell XML element 6 of XML element SPM of XML element 1 of XML element 1 of contents
set a to a & "Memory:" & return & return
repeat with x in XML elements
tell x
set a to a & value of XML element 2 & return & return
repeat with i from 3 to (count XML elements) by 2
set a to a & value of XML element i & ": "
set a to a & value of XML element (i + 1) & return
end repeat
set a to a & return & return
end tell
end repeat
end tell
end tell
end tell
a -- the data
This works really well, thank you for taking the time to show the work. I am trying to expand on it by adding more SPDataTypes, but I am having trouble understanding how the XML element references relate to the , , and tags. For example, I can’t seem to match the nested structure of the XML to the Apple Script syntax of :
tell XML element 1 of XML element 6 of XML element SPH of XML element 1 of XML element 1 of contents
Perhaps I need to draw it out on the chalkboard, but I don’t see it! Is the tag equal to element 1 or is it equal to XML element 1 or XML element 1 or contents?
<?xml version="1.0" encoding="UTF-8"?>
[b]XML element 1[/b]
[b]XML element 1[/b]
[b] XML SPH (1)[/b]
_dataType
SPHardwareDataType
_detailLevel
-2
_items
[b] XML element 6[/b]
[b] XML element 1[/b]
[b] XML element 1[/b]
_name
hardware_overview
in this loop the DataType parameter will be selected
set ParamList to value of XML element 2 of XML elements of XML element 1 of XML element 1 of contents
repeat with i from 1 to count ParamList
if item i of ParamList is "SPHardwareDataType" then
set SPH to i
else if item i of ParamList is "SPMemoryDataType" then
set SPM to i
exit repeat
end if
end repeat
you can also display the values of the XML elements to see, where you are,
for example with separted tell blocks:
tell application "System Events"
tell XML file XMLfile
tell contents
tell XML element 1
tell XML element 1
tell XML element 1
tell XML element 6
tell XML element 1
display dialog value of XML elements as string
end tell
end tell
end tell
end tell
end tell
end tell
end tell
end tell
Outstanding! Thank you! I really appreciate the help. But now I am now back to the same point where I was with using XSLT and Filemaker. It turns out that the structure of the XML files is variable depending upon the model of the Macintosh. For example:
Here is the partial XML output from a PB G4 12" with two Parallel ATA devices (starting at the SPParallelATADataType)-
Because of the way the output is apparently variably nested, the location based in the script (also in a XSLT style page) approach will miss one device on the PB G4 , BUT it will catch BOTH on the Mac Mini.
So I’ve tried to modify the code to test for both kinds of nesting conditions but partial success:
This modified version of your script works for the Powerbook G4 but NOT for the MacMini
set XMLfile to ((path to desktop) as string) & "PBG4.spx"
set {fName, fDate} to {name, creation date} of (info for alias XMLfile)
set a to text 1 thru ((offset of "." in fName) - 1) of fName & " " & short date string of fDate & " " & time string of fDate & return & return
tell application "System Events"
tell XML file XMLfile
set ParamList to value of XML element 2 of XML elements of XML element 1 of XML element 1 of contents
repeat with i from 1 to count ParamList
if item i of ParamList is "SPHardwareDataType" then
set SPH to i
else if item i of ParamList is "SPParallelATADataType" then
set SPT to i
else if item i of ParamList is "SPMemoryDataType" then
set SPM to i
else if item i of ParamList is "SPPowerDataType" then
set SPP to i
exit repeat
end if
end repeat
tell XML element 1 of XML element 6 of XML element SPH of XML element 1 of XML element 1 of contents
set a to a & "Hardware Overview:" & return & return
repeat with i from 3 to (count XML elements) by 2
set a to a & value of XML element i & ": "
set a to a & value of XML element (i + 1) & return
end repeat
set a to a & return & return & return
end tell
tell XML element 2 of XML element 1 of XML element 6 of XML element SPT of XML element 1 of XML element 1 of contents
set a to a & "ParallelATA: BUS 0" & return & return
repeat with x in XML elements
tell x
set a to a & value of XML element 2 & return & return
repeat with i from 3 to (count XML elements) by 2
set a to a & value of XML element i & ": "
set a to a & value of XML element (i + 1) & return
end repeat
set a to a & return & return
end tell
end repeat
end tell
tell XML element 2 of XML element 2 of XML element 6 of XML element SPT of XML element 1 of XML element 1 of contents
set a to a & "ParallelATA BUS 1:" & return & return
repeat with x in XML elements
tell x
set a to a & value of XML element 2 & return & return
repeat with i from 3 to (count XML elements) by 2
set a to a & value of XML element i & ": "
set a to a & value of XML element (i + 1) & return
end repeat
set a to a & return & return
end tell
end repeat
end tell
tell XML element 6 of XML element SPM of XML element 1 of XML element 1 of contents
set a to a & "Memory:" & return & return
repeat with x in XML elements
tell x
set a to a & value of XML element 2 & return & return
repeat with i from 3 to (count XML elements) by 2
set a to a & value of XML element i & ": "
set a to a & value of XML element (i + 1) & return
end repeat
set a to a & return & return
end tell
end repeat
end tell
tell XML element 6 of XML element SPP of XML element 1 of XML element 1 of contents
set a to a & "Power:" & return & return
repeat with x in XML elements
tell x
set a to a & value of XML element 2 & return & return
repeat with i from 3 to (count XML elements) by 2
set a to a & value of XML element i & ": "
set a to a & value of XML element (i + 1) & return
end repeat
set a to a & return & return
end tell
end repeat
end tell
end tell
end tell
When I evaluate the MacMini XML I get the following error: “SystemEvents got an Error - NSReceiverEvaluationScriptError 4”
And using the script on a MacbookPro, since it has only one ATA device (other is SATA) it gets the same NSR… error 4.
Frustrating… Perhaps there is a better way to test ?
Yes, it is really hard to navigate thru the XML elements with Script Editor.
I’m working with Script Debugger, which provides an explorer to see the nested properties at once.
Do you know the Scripting Addition XML Tools by the manufacturer of Script Debugger, Late Night Software,
which is much better then AppleScript’s XML parsing function
It’s up to you to find an algorithm which works on all machines.
For example use this ParamList loop (get a list of values and select the requested one) also for other XML levels.
As I know next to nothing about coding or Applescript, it’s 100% trial and error for me. I just loaded Script Debugger, and I think that will help me over the last hurdle. Many thanks again, great tip about LatenightSW - very cool stuff on their site!
So I’ve tried another approach along the lines of saving the Profiler file as a “Plain Text” file.
Using UI Browser to find the UI elements to find the correct buttons to push I’ve tried repeatedly to get past the Save As Dialog and am failing.
Here’s what I’ve done so far:
set this_item to (choose file)
tell application "System Profiler"
open this_item
my SaveAS_txt(name of (info for this_item))
end tell
on SaveAS_txt(This_name)
tell application "System Events" to tell process "System Profiler"
set frontmost to true
keystroke "2" using {command down}
delay 1
keystroke "s" using {command down, shift down}
tell (pop up button 1 of group 1 of group 1 of sheet 1 of window 1)
click menu item "Plain Text"
end tell
delay 0.3
click button "Save"
repeat until not (exists) -- wait until the sheet close
delay 0.3
end repeat
end tell
end SaveAS_txt
This results in an unspecified System Events Error: System Events got an error: NSReceiverEvaluationScriptError: 4
Any ideas on why the “click” command isn’t working?