Sign in to follow this  
Followers 0
Malharhak

[XML] Read nodes based on their index

4 posts in this topic

#1 ·  Posted (edited)

Hi,

I'm having a problem and can't find an answer on the web about this... So I ask here :

I am working on reading a XML file with _XMLDomWrapper.au3

Here is the xml :

<?xml version="1.0"?>

<User>
    <Theme>
      <X>-4716</X>
      <Y>-4815</Y>
      <Z>12</Z>
    </Theme>
    <Theme>
      <X>42</X>
      <Y>328</Y>
      <Z>36</Z>
    </Theme>
    <Theme>
      <X>63</X>
      <Y>256</Y>
      <Z>78</Z>
    </Theme>
</User>

What I need to do is to read every position and do something like storing it in an array (like pos[1][0] = -4716, pos[1][1] = -4815, etc.)

Here is my current AutoIt code (I deleted parts of the code which are not relevant for this) :

#RequireAdmin
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_UseX64=n
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <nomadmemory.au3>
#include <ButtonConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <_XMLDomWrapper.au3>
#include <AVIConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <TreeViewConstants.au3>
#include <StaticConstants.au3>
#Include <Array.au3>

$openXml = _XMLFileOpen(@scriptdir & "/test.xml")
     Local $i_pos = _XMLGetNodeCount ("/User/*")
     If $i_pos > 0 Then
         Local $arr = _XMLSelectNodes ("/User/*")
Global $xArray[$arr[0] + 1], $yArray[$arr[0] + 1], $zArray[$arr[0] + 1]
         If IsArray($arr) Then
             For $i = 1 To $arr[0]
                 If $arr[$i] = "Theme" Then ; I precise the code works to this point (the array has the good size, the condition is verified)
                     $xArray[$i] = _XMLGetField ("User/*[" & $i & "]/X")
                     $yArray[$i] = _XMLGetField ("User/*[" & $i & "]/Y")
                      $zArray[$i] = _XMLGetField ("User/*[" & $i & "]/Y")   
              MsgBox(0, "", _XMLGetField ("User/*[" & $i & "]/Y"))
                 EndIf
             Next
             GUISetState(@SW_UNLOCK)
         EndIf
     EndIf
_ArrayDisplay($xArray)
_ArrayDisplay($yArray)
</p>

$xArray, $yArray and $zArray are both empty. It seems that it can't read the nodes by their index (basically, my code is doing "User/*[1]/X, then Waypoints/*[2]/X, etc.

I found this piece of code somewhere on google and it is the only resource I found to read nodes by their index.

So if anyone know how to debug this, or just how to basically read every nodes of this form, it would be awesome :)

Edit :

Edited by Malharhak

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

I wrote a simple code for this.

i hope be usefull.

#include <String.au3>
#include <Array.au3>
$iXML = '<?xml version="1.0"?>' & @CRLF  & _
'<User>' & @CRLF & _
'   <Theme>'&@CRLF & _
'     <X>-4716</X>'&@CRLF & _
'    <Y>-4815</Y>'&@CRLF & _
'     <Z>12</Z>'&@CRLF & _
'   </Theme>'&@CRLF & _
'   <Theme>'&@CRLF & _
'     <X>42</X>'&@CRLF & _
'     <Y>328</Y>'&@CRLF & _
'     <Z>36</Z>'&@CRLF & _
'   </Theme>'&@CRLF & _
'   <Theme>'&@CRLF & _
'     <X>63</X>'&@CRLF & _
'     <Y>256</Y>'&@CRLF & _
'     <Z>78</Z>'&@CRLF & _
'   </Theme>'&@CRLF & _
'</User>'
$Dis = iReadXML($iXML)
_ArrayDisplay($Dis,"Array",-1,0,"","|","|X|Y|Z")
Func iReadXML($XML)
    Local $u,$t,$Arr[1][3],$count=0
    $u = _StringBetween($XML, "<User>", "</User>")
    If Not @error Then
        For $i=0 To UBound($u)-1
            $t = _StringBetween($u[$i], "<Theme>", "</Theme>")
            If Not @error Then
                For $j=0 To UBound($t)-1
                    ReDim $Arr[$count+1][3]
                    $temp = _StringBetween($t[$j], "<X>", "</X>")
                    if Not @error Then $Arr[$count][0] = $temp[0]
                    $temp = _StringBetween($t[$j], "<Y>", "</Y>")
                    if Not @error Then $Arr[$count][1] = $temp[0]
                    $temp = _StringBetween($t[$j], "<Z>", "</Z>")
                    if Not @error Then $Arr[$count][2] = $temp[0]
                    $count +=1
                Next
            Else
                SetError(1)
                Return 0
            EndIf
        Next
        Return $Arr
    Else
        SetError(1)
        Return 0
    EndIf
EndFunc
Edited by eManF

Share this post


Link to post
Share on other sites

Hi,

Thanks this seems to work.

But my problem is that I also need to be able to write dynamically on the file, and I don't see how I would add a new <Theme> and his nodes with your method.

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

For Example:

#include <String.au3>
#include <Array.au3>

$iXML = '<?xml version="1.0"?>' & @CRLF  & _
'<User>' & @CRLF & _
'    <Theme>'&@CRLF & _
'        <X>-4716</X>'&@CRLF & _
'        <Y>-4815</Y>'&@CRLF & _
'        <Z>12</Z>'&@CRLF & _
'    </Theme>'&@CRLF & _
'    <Theme>'&@CRLF & _
'        <X>42</X>'&@CRLF & _
'        <Y>328</Y>'&@CRLF & _
'        <Z>36</Z>'&@CRLF & _
'    </Theme>'&@CRLF & _
'    <Theme>'&@CRLF & _
'        <X>63</X>'&@CRLF & _
'         <Y>256</Y>'&@CRLF & _
'        <Z>78</Z>'&@CRLF & _
'    </Theme>'&@CRLF & _
'</User>'

MsgBox(0,0,$iXML)
$Dis = iReadXML($iXML)
_ArrayDisplay($Dis,"Array",-1,0,"","|","|X|Y|Z")

$iXML = iAddTheme($iXML,"100","200",300)

MsgBox(0,0,$iXML)
$Dis = iReadXML($iXML)
_ArrayDisplay($Dis,"Array",-1,0,"","|","|X|Y|Z")

Func iReadXML($XML)
    Local $u,$t,$Arr[1][3],$count=0
    $u = _StringBetween($XML, "<User>", "</User>")
    If Not @error Then
        For $i=0 To UBound($u)-1
            $t = _StringBetween($u[$i], "<Theme>", "</Theme>")
            If Not @error Then
                For $j=0 To UBound($t)-1
                    ReDim $Arr[$count+1][3]
                    $temp = _StringBetween($t[$j], "<X>", "</X>")
                    if Not @error Then $Arr[$count][0] = $temp[0]
                    $temp = _StringBetween($t[$j], "<Y>", "</Y>")
                    if Not @error Then $Arr[$count][1] = $temp[0]
                    $temp = _StringBetween($t[$j], "<Z>", "</Z>")
                    if Not @error Then $Arr[$count][2] = $temp[0]
                    $count +=1
                Next
            Else
                SetError(1)
                Return 0
            EndIf
        Next
        Return $Arr
    Else
        SetError(1)
        Return 0
    EndIf
EndFunc

Func iAddTheme($XML,$X,$Y,$Z,$flag=1)
    Local $newTheme
    If $flag=1 Then
        $newTheme = "    "& "<Theme>" & @CRLF & "    "&"    "& "<X>" & $X & "</X>" & @CRLF & "    "&"    "& "<Y>" & $Y & "</Y>" & @CRLF & "    "&"    "& "<Z>" & $Z & "</Z>" & @CRLF & "    "& "</Theme>" & @CRLF
    Else
        $newTheme = "<Theme>" & "<X>" & $X & "</X>" & "<Y>" & $Y & "</Y>" & "<Z>" & $Z & "</Z>" & "</Theme>"
    EndIf
    $XML = _StringInsert($XML,$newTheme,StringLen($XML)-7)
    Return $XML
EndFunc
Edited by eManF

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  
Followers 0