Plain text output form System Profiler using Automator and AS

Hi,

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)

Hi,

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 :wink:

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

Hi Stefan,

:slight_smile: Yes, agreed saving as text is easier.

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

to:

<?xml version="1.0" encoding="UTF-8"?> _dataType SPHardwareDataType _detailLevel -2 _items MMM_entry MMM_state MMM_enabled SMC_version 1.2f10 _name hardware_overview boot_rom_version MBP11.0055.B03 bus_speed 667 MHz cpu_type Intel Core Duo current_processor_speed 2 GHz l2_cache_share 2 MB machine_model MacBookPro1,1 machine_name MacBookPro15 number_processors 2 packages 1 physical_memory 1 GB serial_number xxxxxxxxxxx

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?

Thanks

Cliff

Hi Cliff,

the structure seems more complicated than it is.

contents
XML element 1

<?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

¨¨

Stefan,

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)-

_dataType
SPParallelATADataType
_detailLevel
-1
_items


_items


_name
MATSHITACD-RW CW-8123
detachable_drive
no
device_model
MATSHITACD-RW CW-8123
device_revision
CA10
device_serial

spata_protocol
atapi
spata_socket_type
internal
spata_unit_number
0


_name
spata_ata_bus


_items


_name
TOSHIBA MK3025GAS
bsd_name
disk0
detachable_drive
no
device_model
TOSHIBA MK3025GAS
device_revision
KA302B
device_serial
X4CL0542S
os9_drivers
no
removable_media
no
size
27.94 GB
smart_status
Verified
spata_protocol
ata
spata_socket_type
internal
spata_unit_number
0
volumes


_name
Macintosh HD
bsd_name
disk0s3
file_system
Journaled HFS+
free_space
14.66 GB
mount_point
/Volumes/Macintosh HD
size
27.82 GB
writable
yes


volumes_anonymous


_name
disk0s3
file_system
Journaled HFS+
free_space
14.66 GB
size
27.82 GB
writable
yes




_name
spata_ata_bus

And here is the XML output for a G4 MacMini that also has two Parallel ATA devices inside -

_dataType
SPParallelATADataType
_detailLevel
-1
_items


_items


_name
IC25N060ATMR04-0
bsd_name
disk0
detachable_drive
no
device_model
IC25N060ATMR04-0
device_revision
MO3OAD4A
device_serial
MRG357K3J7WH1H
os9_drivers
yes
removable_media
no
size
55.89 GB
smart_status
Verified
spata_protocol
ata
spata_socket_type
internal
spata_unit_number
0
volumes


_name
Macintosh HD1
bsd_name
disk0s6
file_system
HFS+
free_space
16.38 GB
mount_point
/
size
55.89 GB
writable
yes


volumes_anonymous


_name
disk0s6
file_system
HFS+
free_space
16.38 GB
size
55.89 GB
writable
yes




_name
MATSHITACD-RW CW-8123
detachable_drive
no
device_model
MATSHITACD-RW CW-8123
device_revision
CAD4
device_serial

spata_protocol
atapi
spata_socket_type
internal
spata_unit_number
1


_name
spata_ata_bus

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 ?

Cliff

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

http://osaxen.com/files/xmltools2.9.html

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.

For me scripting is 50% trial and error :wink:

Stefan,

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!

Cheers!

Cliff

Stefan et. al,

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?

Regards,

Cliff