Jump to content

XML Parse ERROR - Unable to get child data


Recommended Posts

Hi all guys,

I'm not able, using XML.au3, to retrieve data, array format, of nested nodes.

Here is the example.XML I use:

<Main>
    <FirstName>Name</FirstName>
    <LastName>1</LastName> 
    <AddressVerified>True</AddressVerified>
    <IDVerified>True</IDVerified>
    <RoomTypes>
        <Roomtype 1="RoomA" 2="RoomC" 3="RoomE" 4="RoomG" />
        <Roomtype 1="RoomB" 2="RoomD" 3="RoomF" 4="RoomH" />
    </RoomTypes>
    <SubMenu>
       <Children>1</Children>
       <Pets>2</Pets>
       <Furnitures>
            <Furniture Name="Name1" Location="Room1" Price="100" />
            <Furniture Name="Name2" Location="Room1" Price="300" />
            <Furniture Name="Name3" Location="Room2" Price="500" />
       </Furnitures>
    </SubMenu>
</Main>

And here is the code where I can retrieve only first node datas:
 

#include <array.au3>
#include <date.au3>
#include <MsgBoxConstants.au3>
#include "XML.au3"
; This COM Error Hanlder will be used globally (excepting inside UDF Functions)
Global $oErrorHandler = ObjEvent("AutoIt.Error", ErrFunc_CustomUserHandler_MAIN)
#forceref $oErrorHandler
; This is SetUp for the transfer UDF internal COM Error Handler to the user function
_XML_ComErrorHandler_UserFunction(ErrFunc_CustomUserHandler_XML)
Local $sXML_FileFullPath = @ScriptDir & "\Example.xml"
Local $oXMLDoc = _XML_CreateDOMDocument(3)
_XML_Load($oXMLDoc, $sXML_FileFullPath, "", False)

Local $sXPath = "//FirstName"
Local $avalues = _XML_GetValue($oXmlDoc, $sXPath)
_ArrayDisplay($avalues) ; -- WORKS

Local $sXPath1 = "//Furnitures"
Local $oNodesColl = _XML_GetChildNodes($oXmlDoc, $sXPath1)
Local $aNodesColl = _XML_Array_GetNodesProperties($oNodesColl)
_ArrayDisplay($aNodesColl), 'Example_6__XML_GetChildNodes: ' & 'Length=' & $oNodesColl.length & '   XPath=' & $oNodesColl.expr)

#Region XML__Examples.au3 - XML DOM Error/Event Handling

Func ErrFunc_CustomUserHandler_MAIN($oError)

    ConsoleWrite(@ScriptName & " (" & $oError.scriptline & ") : MainScript ==> COM Error intercepted !" & @CRLF & _
            @TAB & "err.number is: " & @TAB & @TAB & "0x" & Hex($oError.number) & @CRLF & _
            @TAB & "err.windescription:" & @TAB & $oError.windescription & @CRLF & _
            @TAB & "err.description is: " & @TAB & $oError.description & @CRLF & _
            @TAB & "err.source is: " & @TAB & @TAB & $oError.source & @CRLF & _
            @TAB & "err.helpfile is: " & @TAB & $oError.helpfile & @CRLF & _
            @TAB & "err.helpcontext is: " & @TAB & $oError.helpcontext & @CRLF & _
            @TAB & "err.lastdllerror is: " & @TAB & $oError.lastdllerror & @CRLF & _
            @TAB & "err.scriptline is: " & @TAB & $oError.scriptline & @CRLF & _
            @TAB & "err.retcode is: " & @TAB & "0x" & Hex($oError.retcode) & @CRLF & @CRLF)
EndFunc   ;==>ErrFunc_CustomUserHandler_MAIN

Func ErrFunc_CustomUserHandler_XML($oError)

    ; here is declared another path to UDF au3 file
    ; thanks to this with using _XML_ComErrorHandler_UserFunction(ErrFunc_CustomUserHandler_XML)
    ;  you get errors which after pressing F4 in SciTE4AutoIt you goes directly to the specified UDF Error Line
    ConsoleWrite(@ScriptDir & '\XML.au3' & " (" & $oError.scriptline & ") : UDF ==> COM Error intercepted ! " & @CRLF & _
            @TAB & "err.number is: " & @TAB & @TAB & "0x" & Hex($oError.number) & @CRLF & _
            @TAB & "err.windescription:" & @TAB & $oError.windescription & @CRLF & _
            @TAB & "err.description is: " & @TAB & $oError.description & @CRLF & _
            @TAB & "err.source is: " & @TAB & @TAB & $oError.source & @CRLF & _
            @TAB & "err.helpfile is: " & @TAB & $oError.helpfile & @CRLF & _
            @TAB & "err.helpcontext is: " & @TAB & $oError.helpcontext & @CRLF & _
            @TAB & "err.lastdllerror is: " & @TAB & $oError.lastdllerror & @CRLF & _
            @TAB & "err.scriptline is: " & @TAB & $oError.scriptline & @CRLF & _
            @TAB & "err.retcode is: " & @TAB & "0x" & Hex($oError.retcode) & @CRLF & @CRLF)
EndFunc   ;==>ErrFunc_CustomUserHandler_XML

; #FUNCTION# ====================================================================================================================
; Name ..........: XML_My_ErrorParser
; Description ...: Changing $XML_ERR_ ... to human readable description
; Syntax ........: XML_My_ErrorParser($iXMLWrapper_Error, $iXMLWrapper_Extended)
; Parameters ....: $iXMLWrapper_Error   - an integer value.
;                  $iXMLWrapper_Extended           - an integer value.
; Return values .: description as string
; Author ........: mLipok
; Modified ......:
; Remarks .......: This function is only example of how user can parse @error and @extended to human readable description
; Related .......:
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func XML_My_ErrorParser($iXMLWrapper_Error, $iXMLWrapper_Extended = 0)
    Local $sErrorInfo = ''
    Switch $iXMLWrapper_Error
        Case $XML_ERR_SUCCESS
            $sErrorInfo = '$XML_ERR_SUCCESS=' & $XML_ERR_SUCCESS & @CRLF & 'All is ok.'
        Case $XML_ERR_GENERAL
            $sErrorInfo = '$XML_ERR_GENERAL=' & $XML_ERR_GENERAL & @CRLF & 'The error which is not specifically defined.'
        Case $XML_ERR_COMERROR
            $sErrorInfo = '$XML_ERR_COMERROR=' & $XML_ERR_COMERROR & @CRLF & 'COM ERROR OCCURED. Check @extended and your own error handler function for details.'
        Case $XML_ERR_ISNOTOBJECT
            $sErrorInfo = '$XML_ERR_ISNOTOBJECT=' & $XML_ERR_ISNOTOBJECT & @CRLF & 'No object passed to function'
        Case $XML_ERR_INVALIDDOMDOC
            $sErrorInfo = '$XML_ERR_INVALIDDOMDOC=' & $XML_ERR_INVALIDDOMDOC & @CRLF & 'Invalid object passed to function'
        Case $XML_ERR_INVALIDATTRIB
            $sErrorInfo = '$XML_ERR_INVALIDATTRIB=' & $XML_ERR_INVALIDATTRIB & @CRLF & 'Invalid object passed to function.'
        Case $XML_ERR_INVALIDNODETYPE
            $sErrorInfo = '$XML_ERR_INVALIDNODETYPE=' & $XML_ERR_INVALIDNODETYPE & @CRLF & 'Invalid object passed to function.'
        Case $XML_ERR_OBJCREATE
            $sErrorInfo = '$XML_ERR_OBJCREATE=' & $XML_ERR_OBJCREATE & @CRLF & 'Object can not be created.'
        Case $XML_ERR_NODECREATE
            $sErrorInfo = '$XML_ERR_NODECREATE=' & $XML_ERR_NODECREATE & @CRLF & 'Can not create Node - check also COM Error Handler'
        Case $XML_ERR_NODEAPPEND
            $sErrorInfo = '$XML_ERR_NODEAPPEND=' & $XML_ERR_NODEAPPEND & @CRLF & 'Can not append Node - check also COM Error Handler'
        Case $XML_ERR_PARSE
            $sErrorInfo = '$XML_ERR_PARSE=' & $XML_ERR_PARSE & @CRLF & 'Error: with Parsing objects, .parseError.errorCode=' & $iXMLWrapper_Extended & ' Use _XML_ErrorParser_GetDescription() for get details.'
        Case $XML_ERR_PARSE_XSL
            $sErrorInfo = '$XML_ERR_PARSE_XSL=' & $XML_ERR_PARSE_XSL & @CRLF & 'Error with Parsing XSL objects .parseError.errorCode=' & $iXMLWrapper_Extended & ' Use _XML_ErrorParser_GetDescription() for get details.'
        Case $XML_ERR_LOAD
            $sErrorInfo = '$XML_ERR_LOAD=' & $XML_ERR_LOAD & @CRLF & 'Error opening specified file.'
        Case $XML_ERR_SAVE
            $sErrorInfo = '$XML_ERR_SAVE=' & $XML_ERR_SAVE & @CRLF & 'Error saving file.'
        Case $XML_ERR_PARAMETER
            $sErrorInfo = '$XML_ERR_PARAMETER=' & $XML_ERR_PARAMETER & @CRLF & 'Wrong parameter passed to function.'
        Case $XML_ERR_ARRAY
            $sErrorInfo = '$XML_ERR_ARRAY=' & $XML_ERR_ARRAY & @CRLF & 'Wrong array parameter passed to function. Check array dimension and conent.'
        Case $XML_ERR_XPATH
            $sErrorInfo = '$XML_ERR_XPATH=' & $XML_ERR_XPATH & @CRLF & 'XPath syntax error - check also COM Error Handler.'
        Case $XML_ERR_NONODESMATCH
            $sErrorInfo = '$XML_ERR_NONODESMATCH=' & $XML_ERR_NONODESMATCH & @CRLF & 'No nodes match the XPath expression'
        Case $XML_ERR_NOCHILDMATCH
            $sErrorInfo = '$XML_ERR_NOCHILDMATCH=' & $XML_ERR_NOCHILDMATCH & @CRLF & 'There is no Child in nodes matched by XPath expression.'
        Case $XML_ERR_NOATTRMATCH
            $sErrorInfo = '$XML_ERR_NOATTRMATCH=' & $XML_ERR_NOATTRMATCH & @CRLF & 'There is no such attribute in selected node.'
        Case $XML_ERR_DOMVERSION
            $sErrorInfo = '$XML_ERR_DOMVERSION=' & $XML_ERR_DOMVERSION & @CRLF & 'DOM Version: ' & 'MSXML Version ' & $iXMLWrapper_Extended & ' or greater required for this function'
        Case $XML_ERR_EMPTYCOLLECTION
            $sErrorInfo = '$XML_ERR_EMPTYCOLLECTION=' & $XML_ERR_EMPTYCOLLECTION & @CRLF & 'Collections of objects was empty'
        Case $XML_ERR_EMPTYOBJECT
            $sErrorInfo = '$XML_ERR_EMPTYOBJECT=' & $XML_ERR_EMPTYOBJECT & @CRLF & 'Object is empty'
        Case Else
            $sErrorInfo = '=' & $iXMLWrapper_Error & @CRLF & 'NO ERROR DESCRIPTION FOR THIS @error'
    EndSwitch

    Local $sExtendedInfo = ''
    Switch $iXMLWrapper_Error
        Case $XML_ERR_COMERROR, $XML_ERR_NODEAPPEND, $XML_ERR_NODECREATE
            $sExtendedInfo = 'COM ERROR NUMBER (@error returned via @extended) =' & $iXMLWrapper_Extended
        Case $XML_ERR_PARAMETER
            $sExtendedInfo = 'This @error was fired by parameter: #' & $iXMLWrapper_Extended
        Case Else
            Switch $iXMLWrapper_Extended
                Case $XML_EXT_DEFAULT
                    $sExtendedInfo = '$XML_EXT_DEFAULT=' & $XML_EXT_DEFAULT & @CRLF & 'Default - Do not return any additional information'
                Case $XML_EXT_XMLDOM
                    $sExtendedInfo = '$XML_EXT_XMLDOM=' & $XML_EXT_XMLDOM & @CRLF & '"Microsoft.XMLDOM" related Error'
                Case $XML_EXT_DOMDOCUMENT
                    $sExtendedInfo = '$XML_EXT_DOMDOCUMENT=' & $XML_EXT_DOMDOCUMENT & @CRLF & '"Msxml2.DOMDocument" related Error'
                Case $XML_EXT_XSLTEMPLATE
                    $sExtendedInfo = '$XML_EXT_XSLTEMPLATE=' & $XML_EXT_XSLTEMPLATE & @CRLF & '"Msxml2.XSLTemplate" related Error'
                Case $XML_EXT_SAXXMLREADER
                    $sExtendedInfo = '$XML_EXT_SAXXMLREADER=' & $XML_EXT_SAXXMLREADER & @CRLF & '"MSXML2.SAXXMLReader" related Error'
                Case $XML_EXT_MXXMLWRITER
                    $sExtendedInfo = '$XML_EXT_MXXMLWRITER=' & $XML_EXT_MXXMLWRITER & @CRLF & '"MSXML2.MXXMLWriter" related Error'
                Case $XML_EXT_FREETHREADEDDOMDOCUMENT
                    $sExtendedInfo = '$XML_EXT_FREETHREADEDDOMDOCUMENT=' & $XML_EXT_FREETHREADEDDOMDOCUMENT & @CRLF & '"Msxml2.FreeThreadedDOMDocument" related Error'
                Case $XML_EXT_XMLSCHEMACACHE
                    $sExtendedInfo = '$XML_EXT_XMLSCHEMACACHE=' & $XML_EXT_XMLSCHEMACACHE & @CRLF & '"Msxml2.XMLSchemaCache." related Error'
                Case $XML_EXT_STREAM
                    $sExtendedInfo = '$XML_EXT_STREAM=' & $XML_EXT_STREAM & @CRLF & '"ADODB.STREAM" related Error'
                Case $XML_EXT_ENCODING
                    $sExtendedInfo = '$XML_EXT_ENCODING=' & $XML_EXT_ENCODING & @CRLF & 'Encoding related Error'
                Case Else
                    $sExtendedInfo = '$iXMLWrapper_Extended=' & $iXMLWrapper_Extended & @CRLF & 'NO ERROR DESCRIPTION FOR THIS @extened'
            EndSwitch
    EndSwitch
    ; return back @error and @extended for further debuging
    Return SetError($iXMLWrapper_Error, $iXMLWrapper_Extended, _
            '@error description:' & @CRLF & _
            $sErrorInfo & @CRLF & _
            @CRLF & _
            '@extended description:' & @CRLF & _
            $sExtendedInfo & @CRLF & _
            '')

EndFunc   ;==>XML_My_ErrorParser
#EndRegion XML__Examples.au3 - XML DOM Error/Event Handling

I would like to get all these info and store them on one or more arrays, no matter, but seems I miss something since I can't retrieve them.

Thanks all in advance,

Marco

Link to post
Share on other sites

To start with, the example XML that you posted is incomplete and invalid.  It does not have an XML tag at the beginning AND you cannot have attribute names like 1, 2, and 3.  XML element names must start with a letter or an underscore.

Whenever you get your XML issues worked out, the examples I posted in the topics below are a few ways, using the xml.au3 UDF, to process XML data into one or more arrays:

 

3 hours ago, marko001 said:

I would like to get all these info and store them on one or more arrays, no matter, but seems I miss something since I can't retrieve them.

For the record, a simple search of the forum, using just "xml AND array", would have lead you to the topics above.

https://www.autoitscript.com/forum/search/?q=xml AND array&quick=1

 

Edited by TheXman
Added 2nd example link
Link to post
Share on other sites

@TheXman I pretty understood how to manage arrays for certain kind of nodes.

I'm still in a mess for nodes like these:

   	<SubMenu>
       <Children>1</Children>
       <Pets>2</Pets>
       <Furnitures>
			<Furniture Name="Name1" Location="Room1" Price="100" />
			<Furniture Name="Name2" Location="Room1" Price="300" />
			<Furniture Name="Name3" Location="Room2" Price="500" />
       </Furnitures>
	</SubMenu>

I can put in arrays "Children" and "Pets" but i'm not able to retrieve info from <Furnitures>

My aim is to get an array like

$aSubMenu_Furnitures[0][3]
; x,0 - Name
; x,1 - Location
; x,2 - Price

So in my case I should get a [3][3] array

$aSubMenu_Furnitures[3][3]
; 0,0 - Name1
; 0,1 - Room1
; 0,2 - 100
; 1,0 - Name2
; 1,1 - Room1
; 1,2 - 300
; 2,0 - Name3
; 2,1 - Room2
; 2,2 - 500

Thanks, dude

Link to post
Share on other sites

I already provided 2 well-documented examples, using the xml.au3 udf, of how to process XML elements into an arrays.  Both of the examples that I provided are very similar to the structures you have given as an example.  For the most part, it's just a matter of understanding the logic, changing the names, and making a few small changes to fit your particular case.  So you need to be more specific as to what problem or problems you're having.  I'm not going to try to guess.  If you would like my help in learning why you are having those problems and how you may be able to resolve them, then post your script (or a short example) and the valid XML that you're using so it can be analyzed.

Edited by TheXman
Link to post
Share on other sites

@TheXman Hi bro!

I got it! I simply needed to use "@" to get the specific field.

$aRoomName = _XML_GetValue($oXml, "//Furnitures/@Name")
    $aRoomLocation = _XML_GetValue($oXml, "//Furnitures/@Location")
    $aRoomPrice = _XML_GetValue($oXml, "//Furnitures/@Price")

Last question (You already answered all of previous ones thanks to the links you provided):

If I have "n" submenus, like in this case:

<SubMenu>
       <Children>1</Children>
       <Pets>2</Pets>
       <Furnitures>
            <Furniture Name="Name1" Location="Room1" Price="100" />
            <Furniture Name="Name2" Location="Room1" Price="300" />
            <Furniture Name="Name3" Location="Room2" Price="500" />
       </Furnitures>
    </SubMenu>
    <SubMenu>
       <Children>2</Children>
       <Pets>2</Pets>
       <Furnitures>
            <Furniture Name="Name1" Location="Room1" Price="100" />
            <Furniture Name="Name2" Location="Room1" Price="300" />
            <Furniture Name="Name3" Location="Room2" Price="500" />
       </Furnitures>
    </SubMenu>

how can I get, for example, Furnitures in case we have 2 Children? (<Children>2</Children>)

Is this the correct form? :
 

$aDetailedFurniture = _XML_GetValue($oXml, "//SubProfile/[Children='2']/Furnitures/Furniture/@Name")

 

Link to post
Share on other sites
14 minutes ago, marko001 said:

I got it! I simply needed to use "@" to get the specific field.

Congrats!  The "@" designates XML attributes.

14 minutes ago, marko001 said:

how can I get, for example, Furnitures in case we have 2 Children? (<Children>2</Children>)

There are numerous ways.  What would help is if you described what the expected result should look like.  Again, the examples that I have already provided show how to process nested arrays (with both static and dynamic numbers of elements).

As I said before, if you want my help, you need to show your script (or at least a valid attempt) so I can understand what you are having an issue with.  Note that I did not say random lines of code without context, I said a script.

 

Edited by TheXman
Link to post
Share on other sites

@TheXman Here we go, I tried to explain also in Console:

<?xml version="1.0" encoding="utf-8"?>
<Main>
    <FirstName>Francois</FirstName>
    <LastName>Rens</LastName> 
    <AddressVerified>True</AddressVerified>
    <IDVerified>True</IDVerified>
    <RoomTypes>
        <Roomtype A="RoomA" B="RoomC" C="RoomE" D="RoomG" />
        <Roomtype A="RoomB" B="RoomD" C="RoomF" D="RoomH" />
    </RoomTypes>
    <SubMenu>
       <Children>1</Children>
       <Pets>2</Pets>
       <Furnitures>
            <Furniture Name="Name1" Location="Room1" Price="100" />
            <Furniture Name="Name2" Location="Room1" Price="300" />
            <Furniture Name="Name3" Location="Room2" Price="500" />
       </Furnitures>
    </SubMenu>
    <SubMenu>
       <Children>2</Children>
       <Pets>2</Pets>
       <Furnitures>
            <Furniture Name="Name4" Location="Room2" Price="400" />
            <Furniture Name="Name5" Location="Room1" Price="600" />
            <Furniture Name="Name6" Location="Room3" Price="800" />
       </Furnitures>
    </SubMenu>
</Main>

and

#include <Constants.au3>
#include <Array.au3>
#include <xml.au3>

_testXML()

Func _testXML()
    Const $XML_FILE = @ScriptDir & "\Demofile.xml" 
    Local $oXML, $oRecord, $oSubRecord
;vars for main Tree
    Local $aRecord[0][4]
    Local $sFirstName, $sLastName, $sAddressVerified, $sIDVerified
;vars for SubMenu
    Local $aSubMenu[0][2]
    Local $sChildren, $sPets
;vars for Furnitures
    Local $aFurnitures[0][3]

;Create XML object
    $oXML = _XML_CreateDOMDocument()
    If @error Then Exit MsgBox($MB_ICONERROR, "ERROR", "XML object creation failed - @error = " & @error)
    ;Load xml file
    _XML_Load($oXML, $XML_FILE)
    If @error Then Exit MsgBox($MB_ICONERROR, "ERROR", "Loading of XML failed - @error = " & @error)

;Get Main Record Data
    $oRecord = _XML_SelectNodes($oXML, "//Main")
    If @error Then Exit MsgBox($MB_ICONERROR, "ERROR", "Error getting contact nodes - @error = " & @error)
    ;Load contact information into the array
    For $val In $oRecord
        ;Populate the fields
        $sFirstName             = _XML_GetValue($val, "FirstName")[1]
        $sLastName          = _XML_GetValue($val, "LastName")[1]
        $sAddressVerified       = _XML_GetValue($val, "AddressVerified")[1]
        $sIDVerified    = _XML_GetValue($val, "IDVerified")[1]
        _ArrayAdd($aRecord, _
                $sFirstName              & "|" & _
                $sLastName       & "|" & _
                $sAddressVerified        & "|" & _
                $sIDVerified)
    Next
    _ArrayDisplay($aRecord, "Main Data", "", 0, Default, "First Name|Last Name|Address Verified|ID Verified")

; Search on SubMenu
    $oSubRecord = _XML_SelectNodes($oXML, "/Main/SubMenu")
    If @error Then Exit MsgBox($MB_ICONERROR, "ERROR", "Error getting contact nodes - @error = " & @error)
    ;Load contact information into the array
    For $val In $oSubRecord
        $sChildren          = _XML_GetValue($val, "Children")[1]
        $sPets              = _XML_GetValue($val, "Pets")[1]
        _ArrayAdd($aSubMenu, _
                $sChildren           & "|" & _
                $sPets)
    Next
    ConsoleWrite("Array shows me both SubMenus, how can I show just, for example, the first?" & @CRLF)
    _ArrayDisplay($aSubMenu, "Example of a Submenu Data", "", 0, Default, "Children|Pets")

; Arrays of attributes
    $aF1 = _XML_GetValue($oXml, "//Furniture/@Name")
    $aF2 = _XML_GetValue($oXml, "//Furniture/@Location")
    $aF3 = _XML_GetValue($oXml, "//Furniture/@Price")
    ReDim $aFurnitures[UBound($aF1)-1][3]
    for $i = 1 to UBound($aF1)-1
        $aFurnitures[$i-1][0] = $aF1[$i]
        $aFurnitures[$i-1][1] = $aF2[$i]
        $aFurnitures[$i-1][2] = $aF3[$i]
    Next
    ConsoleWrite("Also in this case I see both SubMenus" & @CRLF)
    _ArrayDisplay($aFurnitures, "Furnitures")

; Try to get specific Furniture - I want to get Furnitures when Children = 2
    $ans =  InputBox("Children","How Many Children?","2")
;~  $row = _ArraySearch($aSubMenu,$ans,0,0,0,0,1,1)

    $aQueryResult = _XML_GetValue($oXml, "//SubMenu/[Children='" & $ans &"']/Furniture/@Name")
    If @error Then
        MsgBox(0,"Error","Error N. " & @error)
    Else
        _ArrayDisplay($aQueryResult)
    EndIf
EndFunc

 

Link to post
Share on other sites

Like I said, it would help to know what the expected resulting array should look like to know how I would process the xml file. 

Below is an example that will hopefully get you pointed in the right direction.  I tried to make the structure similar to what you are working with.

#AutoIt3Wrapper_AU3Check_Parameters=-w 3 -w 4 -w 5 -w 6 -d

#include <Constants.au3>
#include <Array.au3>
#include <MyIncludes\XML\xml.au3>  ;<== Modify as needed

xml_example()

Func xml_example()
    Const $XML_DATA = _
                      '<?xml version="1.0" encoding="UTF-8" ?>' & _
                      '<Root>' & _
                      '  <Store id="1" name="Store 1">' & _
                      '    <Bags>' & _
                      '      <Bag Name="Brand X" Cost="30.00" />' & _
                      '    </Bags>' & _
                      '    <Bikes>' & _
                      '      <Bike Name="Huffy"   Color="Red"   Cost="100.00" />' & _
                      '      <Bike Name="Schwin"  Color="Blue"  Cost="150.00" />' & _
                      '      <Bike Name="Bianchi" Color="Green" Cost="300.00" />' & _
                      '    </Bikes>' & _
                      '  </Store>' & _
                      '  <Store id="2" name="Store 2">' & _
                      '    <Bikes>' & _
                      '      <Bike Name="Aprilla" Color="Red"    Cost="150.00" />' & _
                      '      <Bike Name="Acme"    Color="Green"  Cost="275.00" />' & _
                      '      <Bike Name="Bianchi" Color="Silver" Cost="300.00" />' & _
                      '    </Bikes>' & _
                      '  </Store>' & _
                      '</Root>'

    Local $oXML, $oStores, $oBikes
    Local $iIndex
    Local $aBikes[0][4]
    Local $sStoreName

    ;Create XML object
    $oXML = _XML_CreateDOMDocument()
    If @error Then Exit MsgBox($MB_ICONERROR, "ERROR", "XML object creation failed - @error = " & @error)

    ;Load the xml into the xml object
    _XML_LoadXML($oXML, $XML_DATA)
    If @error Then Exit MsgBox($MB_ICONERROR, "ERROR", "Loading of XML failed - @error = " & @error)

    ;Get collection of store nodes
    $oStores = _XML_SelectNodes($oXML, "//Root/Store")
    If @error Then Exit MsgBox($MB_ICONERROR, "ERROR", "Error getting nodes - @error = " & @error)

    ;For each store node, load bike information into the array
    $iIndex = -1
    For $oStore in $oStores
        ;Save store name
        $sStoreName = _XML_GetValue($oStore, "@name")[1]

        ;Get collection of bike nodes in store
        $oBikes = _XML_SelectNodes($oStore, "./Bikes/Bike")
        If @error Then Exit MsgBox($MB_ICONERROR, "ERROR", "Error getting nodes - @error = " & @error)

        ;For each bike node, load information into the array
        For $oBike in $oBikes
            ;Add a row to the array and increment the row index
            _ArrayAdd($aBikes, "")
            $iIndex += 1

            ;Populate row columns with values of interest
            $aBikes[$iIndex][0] = $sStoreName
            $aBikes[$iIndex][1] = _XML_GetValue($oBike, "@Name")[1]
            $aBikes[$iIndex][2] = _XML_GetValue($oBike, "@Color")[1]
            $aBikes[$iIndex][3] = _XML_GetValue($oBike, "@Cost")[1]
        Next
    Next

    ;Display furnitures array
    _ArrayDisplay($aBikes, "Bikes by Store", "", 0, Default, "Store|Name|Color|Cost")
EndFunc

image.png.32ecaef8bb766b74e06d5bd84bd2f1f7.png

Edited by TheXman
Link to post
Share on other sites
Posted (edited)

So, if I want to get all bikes available in Store1 I just get it from the resulting array?

In this way I have to load *all* the items in one array.

Is it possible to query it and load only what needed? Let's say I would like to see only bikes on Store 1

 

 

Edit: and... by the way...Bianchi always the most expensive :D

Edited by marko001
Link to post
Share on other sites

You could specify the xpath to retrieve the bike nodes under store 1 in several ways, for example:

/Root/Store[1]/Bikes/Bike

or

//Store[1]/Bikes/Bike

or

/Root/Store[@name='Store 1']/Bikes/Bike (By value)

 

#AutoIt3Wrapper_AU3Check_Parameters=-w 3 -w 4 -w 5 -w 6 -d

#include <Constants.au3>
#include <xml.au3>

Const $XML_DATA = _
                  '<?xml version="1.0" encoding="UTF-8" ?>' & _
                  '<Root>' & _
                  '  <Store id="1" name="Store 1">' & _
                  '    <Address>1234 Any St, Any Town, ABC 48034</Address>' & _
                  '    <Bags>' & _
                  '      <Bag Name="Brand X" Cost="30.00" />' & _
                  '    </Bags>' & _
                  '    <Bikes>' & _
                  '      <Bike Name="Huffy"   Color="Red"   Cost="100.00" />' & _
                  '      <Bike Name="Schwin"  Color="Blue"  Cost="150.00" />' & _
                  '      <Bike Name="Bianchi" Color="Green" Cost="300.00" />' & _
                  '    </Bikes>' & _
                  '  </Store>' & _
                  '  <Store id="2" name="Store 2">' & _
                  '    <Address>7890 Any Ave, Biketown, ABC 90210</Address>' & _
                  '    <Bikes>' & _
                  '      <Bike Name="Aprilla" Color="Red"    Cost="150.00" />' & _
                  '      <Bike Name="Acme"    Color="Green"  Cost="275.00" />' & _
                  '      <Bike Name="Bianchi" Color="Silver" Cost="300.00" />' & _
                  '    </Bikes>' & _
                  '  </Store>' & _
                  '</Root>'

xml_example()

Func xml_example()
    Local $oXML, $oNodeCollection

    ;Create XML object
    $oXML = _XML_CreateDOMDocument()
    If @error Then Exit MsgBox($MB_ICONERROR, "ERROR", "XML object creation failed - @error = " & @error)

    ;Load the xml into the xml object
    _XML_LoadXML($oXML, $XML_DATA)
    If @error Then Exit MsgBox($MB_ICONERROR, "ERROR", "Loading of XML failed - @error = " & @error)

    ;Get collection of nodes
    $oNodeCollection = _XML_SelectNodes($oXML, "/Root/Store[1]/Bikes/Bike") ;By index
    ;$oNodeCollection = _XML_SelectNodes($oXML, "/Root/Store[@name='Store 1']/Bikes/Bike ") ;By value

    If @error Then Exit MsgBox($MB_ICONERROR, "ERROR", "Error getting nodes - @error = " & @error)

    ConsoleWrite("Store 1 Bikes" & @CRLF)
    
    ;For each node in the collection
    For $oNode in $oNodeCollection
        ConsoleWrite(_XML_GetValue($oNode, "@Name")[1] & @CRLF)
    Next
EndFunc

Console

Store 1 Bikes
Huffy
Schwin
Bianchi

 

Edited by TheXman
Added example
Link to post
Share on other sites

@TheXman I saw your XML is 

<Store id="1" name="Store 1">'
<Store id="1" name="Store 1">
..
</Store>

my one is

<Store> 
    <id>1</id>
    <name>Store 1</name>
    ...
</Store>

How can I filter using this format?

I tried

local aFurnitures[0][3]

for $oStore in $oStore
        $sID = _XML_GetValue($oStore,"ID")[1]
        If $sID = 1 Then
            $aF1 = _XML_GetValue($oStore, "//Bike/@name")
            $aF2 = _XML_GetValue($oStore, "//Bike/@Color")
            $aF3 = _XML_GetValue($oStore, "//Bike/@Cost")
            ReDim $aFurnitures[UBound($aF1)-1][3]
            for $i = 1 to UBound($aF1)-1
                $aFurnitures[$i-1][0] = $aF1[$i]
                $aFurnitures[$i-1][1] = $aF2[$i]
                $aFurnitures[$i-1][2] = $aF3[$i]
            Next
        EndIf
        _ArrayDisplay($aFurnitures)
        Exit
    Next

This gives me a strange result: I get the first store, $sID = 1, so If cycle is processed.

But I get bikes data from second store, not first one 

I tried also

$aF1 = _XML_GetValue($oStore, "/[ID='1']/Bike/@name")

but with no success

Link to post
Share on other sites
$oNodeCollection = _XML_SelectNodes($oXML, "/Root/Store[id='1']/Bikes/Bike") ;By value

XML is case-sensitive.

 

If you want a dance partner, then you should go to a club.  😉  I'm getting tired of this back & forth, step-by-step little dance your doing in order to to get to some yet unknown destination/solution.  You keep moving the target and changing the structure of the XML.  I think you have enough to work with now.  If you have any more questions, they need to be well thought out and include all the necessary details including YOUR XML in the format and structure that it exists, a specific question or questions, and specific expected results.

If you want to learn more about xpath, try the XPATH Tutorial on the W3Schools site.

I don't have a problem helping you learn, but you need to be way more focused because I don't have a lot of patience and don't like wasting my time by chasing moving targets. 

"I'm too old to be chasing targets.  It's much easier to shoot them and be done with it."  ~TheXman  😉

Edited by TheXman
Link to post
Share on other sites

@TheXman Thanks for your answer.

But my XML was quite clear, and I tried to convert to your XML since you posted a different one.

<SubMenu>
       <Children>1</Children>
       <Pets>2</Pets>
       <Furnitures>
            <Furniture Name="Name1" Location="Room1" Price="100" />
            <Furniture Name="Name2" Location="Room1" Price="300" />
            <Furniture Name="Name3" Location="Room2" Price="500" />
       </Furnitures>
    </SubMenu>
    <SubMenu>
       <Children>2</Children>
       <Pets>2</Pets>
       <Furnitures>
            <Furniture Name="Name4" Location="Room2" Price="400" />
            <Furniture Name="Name5" Location="Room1" Price="600" />
            <Furniture Name="Name6" Location="Room3" Price="800" />
       </Furnitures>
    </SubMenu>

My intention is, without loading the entire XML into an array, to retrieve Name, Location and Price of the three Furnitures if Children = 2, nothing less, nothing more.

Then we can dance, everyone in a separate club :D

A big hug, dude!

Link to post
Share on other sites
#AutoIt3Wrapper_AU3Check_Parameters=-w 3 -w 4 -w 5 -w 6 -d

#include <Constants.au3>
#include <Array.au3>
#include <MyIncludes\XML\xml.au3>  ;<== Modify as needed

Const $XML_DATA = _
    '<?xml version="1.0" encoding="UTF-8" ?>' & _
    '<Root>' & _
    '    <SubMenu>' & _
    '       <Children>1</Children>' & _
    '       <Pets>2</Pets>' & _
    '       <Furnitures>' & _
    '            <Furniture Name="Name1" Location="Room1" Price="100" />' & _
    '            <Furniture Name="Name2" Location="Room1" Price="300" />' & _
    '            <Furniture Name="Name3" Location="Room2" Price="500" />' & _
    '       </Furnitures>' & _
    '    </SubMenu>' & _
    '    <SubMenu>' & _
    '       <Children>2</Children>' & _
    '       <Pets>2</Pets>' & _
    '       <Furnitures>' & _
    '            <Furniture Name="Name4" Location="Room2" Price="400" />' & _
    '            <Furniture Name="Name5" Location="Room1" Price="600" />' & _
    '            <Furniture Name="Name6" Location="Room3" Price="800" />' & _
    '       </Furnitures>' & _
    '    </SubMenu>' & _
    '</Root>'

xml_example()

Func xml_example()
    Local $oXML, $oNodeCollection
    Local $aFurniture[0][3]

    ;Create XML object
    $oXML = _XML_CreateDOMDocument()
    If @error Then Exit MsgBox($MB_ICONERROR, "ERROR", "XML object creation failed - @error = " & @error)

    ;Load the xml into the xml object
    _XML_LoadXML($oXML, $XML_DATA)
    If @error Then Exit MsgBox($MB_ICONERROR, "ERROR", "Loading of XML failed - @error = " & @error)

    ;Get collection of nodes
    $oNodeCollection = _XML_SelectNodes($oXML, "/Root/SubMenu[Children = '2']/Furnitures/Furniture ")
    If @error Then Exit MsgBox($MB_ICONERROR, "ERROR", "Error getting nodes - @error = " & @error)

    ;For each node in the collection
    For $oNode in $oNodeCollection
        _ArrayAdd($aFurniture, _
            _XML_GetValue($oNode, "@Name")[1] & _
            "|" & _XML_GetValue($oNode, "@Location")[1] & _
            "|" & _XML_GetValue($oNode, "@Price")[1])
    Next

    _ArrayDisplay($aFurniture, "Furniture for Children = 2", "", 0, Default, "Name|Location|Price")
EndFunc

image.png.14bbdfa76a004a52f2e117e4eff8391a.png

:thumbsup:

2 hours ago, marko001 said:

My intention is, without loading the entire XML into an array, to retrieve Name, Location and Price of the three Furnitures if Children = 2, nothing less, nothing more.

Then we can dance, everyone in a separate club

Well, I guess you can go to the club now.  :D

Edited by TheXman
Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...