Looking for help with XMLFind from XMLLib

Hello,

I’m new to applescript and I’m trying to use it for creating some tools for work.
I used to be a programmer a long time ago (assembly, C, bit of Java) so this is all very strange to me. However, I read a lot of tutorials here and there and was able to concatenate some pieces of code.

I’d like to use the XMLFind command to parse specific data from an XML file.
Since I did not know how to use it, I wrote myself some Find command that is unfortunately very rigid and and change to the XML tag I’m looking for is a consequent work in itself (for me ;)).

Here’s an example of the XML file I’m looking into:

Basically, I’d like to understand how to format my XMLFind command to be able to (for example):

  • list all ‘scenario’ containing a ‘configuration’ that has a specific value
  • list all ‘scenario’ with an ‘operation’ name “SetUp”

I guess that with this as a start I’ll be able to extend to my other needs as they rise.

I appreciate your help.

Regs,

Nicolas

Hi, Nicolas. Welcome to MacScripter.

XMLLib is an OSAX by Satimage Software. I haven’t played around with it much myself, but there’s a tutorial here on Satimage’s Web site. Maybe you’ll be able to glean what you want from it.

One thing I’ve noticed while trying the first few examples in the tutorial is that the ‘XMLDisplay’ command shown compiles to ‘XMLNodeInfo’ in Script Editor on my machine. That just means Emmanuel’s changed his mind about what the command should be called since he wrote the tutorial. Don’t worry when you see it happen! :slight_smile:

Edit:

Thinking about it further, what you want may be easier with System Events’s XML Suite:

set XML_path to (path to desktop as Unicode text) & "Test.xml"

tell application "System Events"
	tell contents of XML file XML_path
		tell XML element "package"
			tell (first XML element whose name is "initial-state" and value of XML attribute "name" is "SECURED")
				
				set RSASupportedScenarii to XML elements whose name is "scenario" and value of XML attribute "name" of (XML elements whose name is "configuration") contains "RSA_Supported"
				
				set setupScenarii to XML elements whose name is "scenario" and value of XML attribute "name" of XML element "operation" of XML element "call" of XML element "preamble" is "SetUp"
				
			end tell
		end tell
	end tell
end tell

I prefer to use an XSL file to parse XML. It is built for the purpose; though it can be a bit cryptic at first glance. You can then use the built-in Unix xsltproc command to transform the xml via the xsl.

First I’ll put the xsl file contents (2 files), for the two ways you wanted to search. These forums always translate the XML/HTML line endings entities, which is annoying; don’t know how to stop that; but read the comment.

To get the scenarios which match a configuration name (this is an xsl file):

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version=“1.0” xmlns:xsl=“http://www.w3.org/1999/XSL/Transform”>
<xsl:output method=“text” version=“1.0” encoding=“utf-8” indent=“yes” />
<xsl:template match=“/”>
<xsl:for-each select=“package/initial-state/scenario/configuration/@name[.=‘ProfileUICC’]”>
<xsl:value-of select=“…/…/@name” />

xsl:textXML/HTML line feed entity here</xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

To get the scenarios which match an operation name (another xsl file):

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version=“1.0” xmlns:xsl=“http://www.w3.org/1999/XSL/Transform”>
<xsl:output method=“text” version=“1.0” encoding=“utf-8” indent=“yes” />
<xsl:template match=“/”>
<xsl:for-each select=“package/initial-state/scenario/preamble/call/operation/@name[.=‘SetUp’]”>
<xsl:value-of select=“…/…/…/…/@name” />

xsl:textXML/HTML line feed entity here</xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

To use each of the two files above to parse the original XML file (AppleScript):


set xml_file to quoted form of POSIX path of (choose file with prompt "XML File")
set xsl_file to quoted form of POSIX path of (choose file with prompt "XSL File")

-- return results here
set txt to do shell script "xsltproc " & xsl_file & " " & xml_file

set lst to paragraphs of txt

Ok, thanx a lot for your feedback and ideas :wink:

To Nigel:
I have started my script with the tutorial from satimage, practised for a few days but the issue I had was that the XML format of my file is not the same as the one they use in their example. I’m sorry, there’s probably some accurate name to qualify the differences but I’m no XML expert.
Their XML file is like

Basically they use only tags with values whereas I also have attributes and I tend to mix all up :frowning:
This is why I do not know how to format a XMLFind request to cope with my XML format.

But I might as well try your option which does not require any extra library (better). I did not know it was possible to do that with System Events.
I think I’ll give it a shot.

To Fenton:
I discovered xsl and it looks a bit tough to setup. The problem I see is that I need to create a dedicated xsl file for each configuration I need to find.
I was looking for something flexible and it does not look this way to me (at this moment).
I’m sorry but I think I’ll try Nigel’s proposal before anything else.

For example, here’s a bit of my script parsing my file with my own construction of a XMLFind-like:

to parseXMLForConfiguration(configurationSearchLocal, outputFileLocal, inputFileLocal)
	try
		-- open the package file
		set XMLFile to XMLOpen inputFileLocal
		-- set the root of the file and get its size
		set rootPackage to XMLRoot XMLFile
		set packageSize to XMLCount rootPackage
		set initialStateNumber to 1
		repeat -- loop on initial states at package level
			repeat -- find an initial state not empty
				set initialState to XMLChild rootPackage index initialStateNumber without all nodes
				set maxNumberOfScenarios to XMLCount initialState
				if maxNumberOfScenarios = 0 then
					set initialStateNumber to initialStateNumber + 1
				else
					exit repeat
				end if
			end repeat -- from here we have a not empty initialState node
			set initialStateName to XMLGetAttribute initialState name "name"
			set scenarioNumber to 1
			repeat -- loop on scenarios at initial state level
				set currentScenario to XMLChild initialState index scenarioNumber
				set scenarioSize to XMLCount currentScenario
				set configurationParsed to false
				if scenarioSize is not 0 then
					-- scenario is not empty
					set currentScenarioName to (XMLGetAttribute currentScenario name "name")
					set scenarioNodeNumber to 1
					repeat -- loop at scenario node level
						set scenarioNode to XMLChild currentScenario index scenarioNodeNumber
						if (XMLTagName scenarioNode) is not equal to "configuration" then
							if configurationParsed then exit repeat
						else
							-- if node is a configuration
							set configurationParsed to true
							set configName to XMLGetAttribute scenarioNode name "name" -- retrieve config name
							if configName is equal to configurationSearchLocal then
								-- store the config name & scenario & init state & package
								write (XMLGetAttribute rootPackage name "name") & " > " & initialStateName & " > " & currentScenarioName & " > " & configName & " vs. " & configurationSearchLocal & crlf to outputFileLocal
							end if
						end if
						set scenarioNodeNumber to scenarioNodeNumber + 1
						if (scenarioNodeNumber ≥ scenarioSize + 1) then exit repeat
					end repeat
				end if
				set scenarioNumber to scenarioNumber + 1
				if (scenarioNumber ≥ maxNumberOfScenarios + 1) then exit repeat
			end repeat
			write "------> " & initialStateName & " index " & (initialStateNumber as string) & " of " & (packageSize as string) to outputFileLocal
			display dialog "completed for " & initialStateName & " index " & (initialStateNumber as string) & " of " & (packageSize as string) giving up after 3
			set initialStateNumber to initialStateNumber + 1
			if (initialStateNumber ≥ packageSize) then exit repeat
		end repeat
		display dialog "Package " & (XMLGetAttribute rootPackage name "name") & " finished"
		XMLClose XMLFile
	on error return
	end try
end parseXMLForConfiguration

Well, I know it’s rookie’s style but it made me happy :smiley:
Hopefully I find some more optimized way soon.
Thanx for your help, I appreciate any comment on how to improve my code :lol:

Hello Nigel and all,

long time no post but I have been using my little scripts for a while. They work ok, simply very complicated.
So now I have to do more complicated work on my XML files.

My first problem here is fairly simple:
I’ve been trying the script from Nigel, using different combinations and they seem to return “stuff”.

But my ignorance in applescript is such that I don’t know how to read the content of RSASupportedScenarii (for ex).
I’d like to output it to a file but I need to put my hands on the properties.

Thanx a lot for your help & advices.

OK, I made some progress. I can get the name of a scenario with:

get value of XML attribute “name” of (item i of RSASupportedScenarii) as string

Next challenge, being able to get the scenarios from all initial-state and not only from one. The goal is not to have to enumerate them because it might be non-exhautive.

Thanx again for your contribution :slight_smile:

Hi, Nicolas. Well done.

Sorry I’ve been quite occupied this weekend. Also, I’ve found that, on my system, the items in the lists returned by my script are unusable. When I try to extract their properties, values, etc. I get an error saying they’re invalid references. (That is, they’re invalid object specifiers. I can get their properties using the filter references which return them. Weird.) I don’t know if this is a glitch in my system, a bug in System Events’s XML Suite, or something to do with the way I’ve stitched up the bleeding stump of your XML fragment to work on the script. It would also help to know exactly what is (or might be) in the full XML and what information you want to extract from it.

Hi Nigel,

your problems might come from the fact that you don’t have the full XML because it’s working on my side.
I can send it to you zipped (130kB) if you wish. It would be one of many but they are all alike.
Let me know.

What I’m looking for in those files is actually many things :smiley:
The more I work with the files, the more I have needs for them.

I need to manage to write my own queries as the logic is not straight forward for me. This textual semantic is quite weird to me.

Here’s an other example of XML of which I’m working on at the moment:

I’m looking for all the scenarios with scenario/preamble/call/observations/operation/argument/value=SUCCESS.
Based on the example above from Nigel, I adapted:

set XML_path to (path to desktop as Unicode text) & "Test.xml"

tell application "System Events"
	tell contents of XML file XML_path
		tell XML element "package"
			tell (first XML element whose name is "initial-state" and value of XML attribute "name" is "OPREADY")
								
				set errorSWScenarii to XML elements whose name is "scenario" and value of XML attribute "name" of XML element "value" of XML element "argument" of XML element "operation" of XML element "observations" of XML element "call" of XML element "body" is "SUCCESS"
			end tell
		end tell
	end tell
end tell 				

but strangely enough I don’t get my scenarios … :frowning:
There is only one “body” per “scenario” so it’s fairly easy to check.
Some match and some don’t without a single reference to “SUCCESS”.

I have to say that I don’t have a clue why this is.
If I can’t trust that tool, it’s unfortunately pointless for me as it’s for work.

I keep looking but any help is appreciated.

PS: it’s also fairly slow compared to the other Sile lib I was using but I think I understand it better.

Regs,

Nicolas