transform XML object to AHK object

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
toralf
Posts: 868
Joined: 27 Apr 2014, 21:08
Location: Germany

transform XML object to AHK object

26 Jun 2018, 07:45

I want to read an XML file and extract data from it.
Is there a way to get the data into a AHK array or object?

So far I was trying this:

Code: Select all

  FileRead, XMLText, % Path
  Xml := loadXML(XMLText)
  ObjTree(XML)
Return

loadXML(ByRef data) {
  o := ComObjCreate("MSXML2.DOMDocument.6.0")
  o.async := false, o.loadXML(data)
  return o
}
with ObjTree by HotKeyIt (https://github.com/HotKeyIt/ObjTree)

But unfortunately ObjectTree gives me an error. I assume it is due to the object being a XML ComObject and not a regualar AHK object.

Is there a way to transform the XML ComObject and not a regualar AHK object?
Or is there a good alternative to ObjTree to visualize the structure of an XML object?

At the end I do not only want to visualize it, i need to loop through the right level of the structure and get the right data.
ciao
toralf
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: transform XML object to AHK object

26 Jun 2018, 13:22

Generally AHK Objects and xml objects are incompatible.
You can modify either to make it compatible with the other - however I don't think that is your goal.
The easiest way to show this incompatibility is this xml:

Code: Select all

<date>
<dates entryNr="1">10-06-1988</date>
<dates entryNr="2">11-06-1988</date>
</date>
What kind of AHK Object would you turn this into?
While there is a simple answer for this specific xml however for all types of xml it's impossible.

I reccomend learning the XML DOM which is just like the HTML DOM.
It is used in many languages and can help you develop programs more easily in all of them.
If you want to visualize the data just read the xml.

EDIT: I reccomend: https://www.w3schools.com/xml/default.asp for learning about xml
Recommends AHK Studio
User avatar
kczx3
Posts: 1640
Joined: 06 Oct 2015, 21:39

Re: transform XML object to AHK object

26 Jun 2018, 18:28

Agreed. XML simply is not represented by objects like those in AHK or JavaScript. Attributes are kind of what make it difficult. You certainly can do it if you define a spec to always follow.
User avatar
FanaticGuru
Posts: 1906
Joined: 30 Sep 2013, 22:25

Re: transform XML object to AHK object

27 Jun 2018, 16:18

toralf wrote:I want to read an XML file and extract data from it.
Is there a way to get the data into a AHK array or object?

So far I was trying this:

Code: Select all

  FileRead, XMLText, % Path
  Xml := loadXML(XMLText)
  ObjTree(XML)
Return

loadXML(ByRef data) {
  o := ComObjCreate("MSXML2.DOMDocument.6.0")
  o.async := false, o.loadXML(data)
  return o
}
with ObjTree by HotKeyIt (https://github.com/HotKeyIt/ObjTree)

But unfortunately ObjectTree gives me an error. I assume it is due to the object being a XML ComObject and not a regualar AHK object.

Is there a way to transform the XML ComObject and not a regualar AHK object?
Or is there a good alternative to ObjTree to visualize the structure of an XML object?

At the end I do not only want to visualize it, i need to loop through the right level of the structure and get the right data.
I don't think there is an easy way to change an XML to an AHK array object. I am sure you could transverse though the nodes and build an array but some decisions would have to be made how to deal with attributes.

If you just want to create something visual, you can transverse the nodes and build a display with indents.

Code: Select all

xmlString = 
(
<?xml version="1.0" encoding="UTF-8"?>
<breakfast_menu>
<food type="good" serve="hot">
    <name>Belgian Waffles</name>
    <price>$5.95</price>
    <description>
   Two of our famous Belgian Waffles with plenty of real maple syrup
   </description>
    <calories>650</calories>
</food>
<food>
    <name>Strawberry Belgian Waffles</name>
    <price>$7.95</price>
    <description>
    Light Belgian waffles covered with strawberries and whipped cream
    </description>
    <calories>900</calories>
</food>
<food>
    <name>Berry-Berry Belgian Waffles</name>
    <price>$8.95</price>
    <description>
    Belgian waffles covered with assorted fresh berries and whipped cream
    </description>
    <calories>900</calories>
</food>
<food>
    <name>French Toast</name>
    <price>$4.50</price>
    <description>
    Thick slices made from our homemade sourdough bread
    </description>
    <calories>600</calories>
</food>
<food style="meal">
		<name>Homestyle Breakfast</name>
		<price>$6.95</price>
		<description>
		Two eggs, bacon or sausage, toast, and our ever-popular hash browns
		</description>
		<calories>950</calories>
</food>
</breakfast_menu> 
)

xDoc := ComObjCreate("MSXML2.DOMDocument.6.0")
xDoc.LoadXml(xmlString)

gui, Add, Text,, % printXML(xDoc.childNodes)
gui Show

Esc::ExitApp

printXML(xNodes, indentLevel="")
{
	for xNode in xNodes
	{
		if (SubStr(list, -1) != "`n`n")
			if (xNode.parentNode.Attributes.Item(0))
			{
				for attr in xNode.parentNode.Attributes
					attrText .= " " attr.Name "=" attr.nodeValue 
				list.= indentLevel "[" xNode.parentNode.nodeName attrText "]"
			}
			else
				list.= indentLevel "[" xNode.parentNode.nodeName "]"
		else
			list := RTrim(list, "`n")
		if (xNode.hasChildNodes )
			list.="`n" printXML(xNode.childNodes, indentLevel . "    ")
		Else
			list.=" => " Trim(xNode.nodeValue, "`n`t ")
		list.="`n"
	}
	return list
}
You could instead use the same framework to create an array, build a tree, collapsing folders, whatever.

This was done quickly and barely tested so it is just an example of possibilities.

FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks
toralf
Posts: 868
Joined: 27 Apr 2014, 21:08
Location: Germany

Re: transform XML object to AHK object

02 Jul 2018, 05:10

Thank you so much for your assistance.

I have learned,
a) that element tags are not necessarily unique among siblings.
b) attribute names are unique within an element
c) a element can either have children or a value

If all the above are correct, I can understand that it is difficult to transform the xml in a general way to an AHK-Object.
It would be an Array of elements where each Element is a associated array with the keys attribute, children or value. While the value for attributes could be an associated array and the value for children would be an array and the value for Value would just be the value itself.

Thus the big disadvantage is a). It makes the object very clumpy and difficult to find the right information.

Thus, I will have to get used to use the XML to find the right information. But who am I going to do it? E.g. I would like to find in the above example the price of the food that has the attribute style with the value meal?
ciao
toralf
User avatar
kczx3
Posts: 1640
Joined: 06 Oct 2015, 21:39

Re: transform XML object to AHK object

02 Jul 2018, 06:59

Your XPath expression would be something like this: /breakfast_menu/food[@style = "meal"]/price. If instead you want the entire food node where the style is "meal", then just chop off the "/price".
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: transform XML object to AHK object

02 Jul 2018, 08:05

Yeah well xml objects are as you described except that they can have both text value and children it's just not commonly done.
AN XML Node as AHK Object:

Code: Select all

class xmlNode {
	children := [] ;all the children nodes that are inside
	text := "" ;the text inside the node
	attributes := {} ;all attributes
	tagName := ""
}
Recommends AHK Studio
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: transform XML object to AHK object

02 Jul 2018, 10:00

One possible solution to the 'can't have children and a value' problem, is to create key names like: A\B\C, thus, each key name contains all of the hierarchy (parent/children) information, and each key can have a value.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
FanaticGuru
Posts: 1906
Joined: 30 Sep 2013, 22:25

Re: transform XML object to AHK object

02 Jul 2018, 13:50

kczx3 wrote:Your XPath expression would be something like this: /breakfast_menu/food[@style = "meal"]/price. If instead you want the entire food node where the style is "meal", then just chop off the "/price".
An example of using XPath with the above XML data and printXML function.

Code: Select all

MsgBox % printXML(xDoc.SelectNodes("/breakfast_menu/food[@style = ""meal""]/price"))
Note you have to two quote (""meal"") the quotes inside quotes for AHK.

If also important to realize this is SelectNodes with an 's'. It is going to return a collection of nodes as you are not guaranteed a unique query result.

To get the actual value of price you could do:

Code: Select all

xNodes := xDoc.SelectNodes("/breakfast_menu/food[@style = ""meal""]/price")
MsgBox % xNodes.Item(0).childNodes.Item(0).nodeValue
Again, realizing you are dealing with collections. The node could have two or more prices. For example the first one being the regular price and second being a sale price. It would be nice to give them attributes to distinguish something like that but XML does not require it. This is one of the things that makes XML different from a typical array structure. There could be a thousand prices that are just a running history of every price of ever one of this item sold where the 5th price is the 5th back item sold.

This is working with the XPath given. In reality it would be better to use a more complex needle to get the specific nodes and values. XPath is kind of like an RegEx needle. It is its own little language for filtering XML.

FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: dunnerca, wilkster and 131 guests