Jump to content
Sign in to follow this  
carabusu

XML recursive

Recommended Posts

carabusu

How can I recursive traverse an XML file to display all children in this order:

parent->child 1->child 1-1; parent->child1->child 1-2; parent->child2 ....

Thanks.

Share this post


Link to post
Share on other sites
carabusu

I've tried something like this :

func traverse($xpath)
    msgbox(4096,"",$xpath)
    $nodesArray=_XMLGetChildNodes($xpath)
    
    if (IsArray($nodesArray) ) Then
            
            
            if Not($nodesArray[0]==0) Then
                for $i=1 to $nodesArray[0]
                    
                    $index=1
                    for $j=1 to $i-1
                    
                        if $nodesArray[$i]==$nodesArray[$j] Then $index=$index+1
                        
                    Next
                ;msgbox(4096,"",$i)
                ;msgbox(4096,"",$xpath & "/" & $nodesArray[$i] & "[" & $index & "]")
                ;msgbox(4096,"",_XMLGetPath($xpath &"/"&$nodesArray[$i]))
                    $areNodes=_XMLGetChildNodes($xpath & "/" & $nodesArray[$i])
                    if not($areNodes[0]==0) Then
                        traverse($xpath & "/" & $nodesArray[$i] & "[" & $index & "]")
                        
                    EndIf   
                Next;for $i=1 to $nodesArray[0]
                
            EndIf;if Not($nodesArray[0]==0) Then
        EndIf;if (IsArray($nodesArray) ) Then
    
EndFunc

but I have this error:

Array variable has incorrect number of subscripts or subscript dimension range exceeded.:

if $nodesArray[$i]==$nodesArray[$j] Then $index=$index+1

if ^ ERROR

Share this post


Link to post
Share on other sites
weaponx

Recursion is so ugly yet so elegant. This will dump all tag names and attributes. It doesn't dump values but that's easy to add. Good luck.

Code:

#include "..\_XMLDomWrapper.au3"

$sXMLFile = "config.xml"

$result = _XMLFileOpen($sXMLFile)
if $result = 0 then Exit

Traverse()

Func Traverse($path = "/", $depth = 0)
    
    Local $indent = ""
    Local $aKeys[1], $aValues[1] ;Arrays used for attributes
    
    ;If current level is greater than zero
    If $depth Then
        ;Add tabs for indentation
        For $Z = 1 to $depth
            $indent &= @TAB
        Next
    EndIf    

    $array = _XMLGetChildNodes($path)
    If $path = "/" Then $path = ""
    If IsArray($array) Then
        ConsoleWrite("!" & $indent & "Path: " & $path & @CRLF) ;Output indexed path in red
        For $X = 1 to $array[0]
            ConsoleWrite($indent & "[" & $X & "]: Element: " & $array[$X]) ;Output tag name
            _XMLGetAllAttrib($path & "/*[" & $X & "]",$aKeys, $aValues) ;Retrieve all attributes
            If NOT @ERROR Then
                ConsoleWrite(" - Attributes: ")
                For $Y = 0 to Ubound($aKeys)-1
                    ConsoleWrite($aKeys[$Y] & "=" & $aValues[$Y] & ", ") ;Output all attributes
                Next
            EndIf
            ConsoleWrite(@CRLF)
            
            Traverse($path & "/*[" & $X & "]", $depth+1)
        Next
        ConsoleWrite(@CRLF)
    EndIf
EndFunc

XML:

<?xml version="1.0"?>
 <menu>
   <folder name="Spyware" oscode="255">
     <folder name="Install" oscode="255">
       <folder name="Silent" oscode="255">
         <item name="Great-Grandchild item" target="PATH\TO\PROGRAM.EXE" oscode="255"/>
       </folder>
       <item name="Grandchild item" target="PATH\TO\PROGRAM.EXE" oscode="255"/>
     </folder>
     <item name="Child item" target="PATH\TO\PROGRAM.EXE" oscode="255"/>
     <folder name="TEST" oscode="255">
       <item name="Great-Grandchild item" target="PATH\TO\PROGRAM.EXE" oscode="255"/>
     </folder>
   </folder>
   <item name="Root item" target="PATH\TO\PROGRAM.EXE" oscode="255"/>
   <folder name="Antivirus" oscode="255">
     <item name="Another child item" target="PATH\TO\PROGRAM.EXE" oscode="255"/>
   </folder>
 </menu>

Output:

!Path: 
[1]: Element: menu
!   Path: /*[1]
    [1]: Element: folder - Attributes: name=Spyware, oscode=255, 
!       Path: /*[1]/*[1]
        [1]: Element: folder - Attributes: name=Install, oscode=255, 
!           Path: /*[1]/*[1]/*[1]
            [1]: Element: folder - Attributes: name=Silent, oscode=255, 
!               Path: /*[1]/*[1]/*[1]/*[1]
                [1]: Element: item - Attributes: name=Great-Grandchild item, target=PATH\TO\PROGRAM.EXE, oscode=255, 

            [2]: Element: item - Attributes: name=Grandchild item, target=PATH\TO\PROGRAM.EXE, oscode=255, 

        [2]: Element: item - Attributes: name=Child item, target=PATH\TO\PROGRAM.EXE, oscode=255, 
        [3]: Element: folder - Attributes: name=TEST, oscode=255, 
!           Path: /*[1]/*[1]/*[3]
            [1]: Element: item - Attributes: name=Great-Grandchild item, target=PATH\TO\PROGRAM.EXE, oscode=255, 


    [2]: Element: item - Attributes: name=Root item, target=PATH\TO\PROGRAM.EXE, oscode=255, 
    [3]: Element: folder - Attributes: name=Antivirus, oscode=255, 
!       Path: /*[1]/*[3]
        [1]: Element: item - Attributes: name=Another child item, target=PATH\TO\PROGRAM.EXE, oscode=255,
Edited by weaponx

Share this post


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
Sign in to follow this  

×