Jump to content

Recommended Posts

Posted

but _XMLSetAttribute is not found in _XMLDomWrapper.au3

???

----------------------------------------------

are you sure is not _XMLSetAttrib("/App/Function/Test/SN/Member","Path","G:\New.path")

That is what I get for staying up too late.

Posted (edited)

Ok, for some reason my script screwed up and it will only write to the first node:

$Result = _XMLFileOpen(GUICtrlRead($KeysXML))
            If $Result = 0 Or $Result = -1 And $Proceed = 1 Then
                MsgBox(16, "Error", "Unable to open XML file!")
                $Proceed = 0
            EndIf

                $Path = "//Keys"
            $NodesArray = _XMLGetChildNodes($Path)
          For $x = 1 To $NodesArray[0] And $Proceed = 1
                        $CheckKey = CheckKey(_XMLGetAttrib($Path & "/Key[" & $x & "]", "SpellID"))
                        If $CheckKey = -1 Then
                            MsgBox(16, "Error", "Unable to read process memory!")
                            $Proceed = 0
                        EndIf
                        If $Bar <> "" Then
                            $GetStatus = StringSplit($Bar, "|")
                            If $GetStatus[0] = 2 Then
                                If $CheckKey = 1 Then
                                    _XMLSetAttrib($Path & "/Key[" & $x & "]", "BarState", $GetStatus[1])
                                    MsgBox(0, "Test", $GetStatus[1] & " written to node " & $x)
                                    _XMLSetAttrib($Path & "/Key[" & $x & "]", "Char", $GetStatus[2])
                                    MsgBox(0, "Test", $GetStatus[2] & " written to node " & $x)
                                EndIf
                            EndIf
                        EndIf
Next

Can anyone help me please?

Edited by =sinister=
Posted (edited)

Ok, for some reason my script screwed up and it will only write to the first node:

$Result = _XMLFileOpen(GUICtrlRead($KeysXML))
            If $Result = 0 Or $Result = -1 And $Proceed = 1 Then
                MsgBox(16, "Error", "Unable to open XML file!")
                $Proceed = 0
            EndIf

                $Path = "//Keys"
            $NodesArray = _XMLGetChildNodes($Path)
          For $x = 1 To $NodesArray[0] And $Proceed = 1
                        $CheckKey = CheckKey(_XMLGetAttrib($Path & "/Key[" & $x & "]", "SpellID"))
                        If $CheckKey = -1 Then
                            MsgBox(16, "Error", "Unable to read process memory!")
                            $Proceed = 0
                        EndIf
                        If $Bar <> "" Then
                            $GetStatus = StringSplit($Bar, "|")
                            If $GetStatus[0] = 2 Then
                                If $CheckKey = 1 Then
                                    _XMLSetAttrib($Path & "/Key[" & $x & "]", "BarState", $GetStatus[1])
                                    MsgBox(0, "Test", $GetStatus[1] & " written to node " & $x)
                                    _XMLSetAttrib($Path & "/Key[" & $x & "]", "Char", $GetStatus[2])
                                    MsgBox(0, "Test", $GetStatus[2] & " written to node " & $x)
                                EndIf
                            EndIf
                        EndIf
Next

Can anyone help me please?

There's not enough of your script to run it but the following works

Edit: Also the xml below is from the last time so there is not a "SpellID" attribute.

#Include <_XMLDomWrapper.au3>
Local $xml = '<?xml version="1.0" encoding="utf-16"?> '  & _
'<Keys> '  & _
'<Key KeyName="Common.TargetParty4" BarState="Indifferent" ShiftState="None" VK="F5" /> '  & _
'<Key KeyName="Common.TargetSelf" BarState="Indifferent" ShiftState="None" VK="F1" /> '  & _
'<Key KeyName="Common.Time1" BarState="Indifferent" ShiftState="None" Char="Undefined" /> '  & _
'<Key KeyName="Common.Time30" BarState="Indifferent" ShiftState="None" Char="Undefined" /> '  & _
'<Key KeyName="Common.Time5" BarState="Indifferent" ShiftState="None" Char="Undefined" /> '  & _
'<Key KeyName="Pogue.Stealth" BarState="Bar5" ShiftState="None" Char="3" /> '  & _
'<Key KeyName="Pogue.Ranged" BarState="Bar6" ShiftState="None" Char="-" /> '  & _
'<Key KeyName="Pogue.Sinister" BarState="Bar1" ShiftState="None" Char="1" /> '  & _
'</Keys>'

_XMLLoadXML($xml)
$Path = "//Keys"
_XMLSetAttrib($Path & "/Key[3]", "BarState", "Unknown")
_XMLSetAttrib($Path & "/Key[3]", "Char","9")
ConsoleWrite($objDoc.xml &@LF)
Edited by eltorro
Posted

This is correct:

_XMLSetAttrib("/App/Function/Test/SN/Member","Path","G:\New.path")

The problem is in your XML, the header is invalid.

This:

<?app version="1.0.0.0"?>

Should be:

<?xml version="1.0"?>

the xml is the config of a program
Posted

I need help with adding a reference to an external XSL file to the beginning of my XML file.

I have XML output using _XMLWrapper that looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<TestResult>
<TestCase>
<Name>scn01_1000Cubes_1view_Wireframe</Name>
<AvgTime>1700.82353181363</AvgTime>
<FPS>58.8</FPS>
<BaseLine1>baseline\scn01_1000Cubes_1view_Wireframe_begin.jpg</BaseLine1>
<BaseLine2>baseline\scn01_1000Cubes_1view_Wireframe_end.jpg</BaseLine2>
<Capture1>capture\scn01_1000Cubes_1view_Wireframe_begin.jpg</Capture1>
<Capture2>capture\scn01_1000Cubes_1view_Wireframe_end.jpg</Capture2>
<Diff1>diff\scn01_1000Cubes_1view_Wireframe_begin.jpg</Diff1>
<Diff2>diff\scn01_1000Cubes_1view_Wireframe_end.jpg</Diff2>
<PixelDiff1>189783</PixelDiff1>
<PixelPercent1>21.37</PixelPercent1>
<PixelDiff2>189783</PixelDiff2>
<PixelPercent2>21.37</PixelPercent2>
</TestCase>

I need to add this:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="result.xsl"?>
<TestResult>

Here is an example of the XSL file, which is formating the XML data out to an HTML table.

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

<xsl:template match="/">
 <html>
 <body>
   <h2>Softimge Certification Results</h2>

   <p></p>
   <table border="2">
    <tr>
    <td colspan="8" bgcolor="#ffcccc"><b><center>OpenGL</center></b></td>
    </tr>
     <tr bgcolor="#ffcccc">
       <!-- <th>TestcaseID</th> -->
       <th>Name</th>
       <th>Baseline</th>
       <th>ScreenCapture</th>
       <th>Comparison</th>
       <th>Difference</th>
       <th>Time</th>
       <th>Pass</th>
       <th>Status</th>
     </tr>
     <xsl:for-each select="TestResult/TestCase">
     <tr>
       <!-- <td><xsl:value-of select="TestcaseID"/></td> -->
       <td><p><xsl:value-of select="Name"/></p><p align="center">Begin Frame</p></td>
       <td><a href="{BaseLine1}"><img src="{BaseLine1}" width="150" height="100"/></a></td>
       <td><a href="{Capture1}"><img src="{Capture1}" width="150" height="100"/></a></td>
       <td><a href="{Diff1}"><img src="{Diff1}" width="150" height="100"/></a></td>
       <xsl:choose>
         <xsl:when test="PixelPercent1 &lt; '1'">
           <td><xsl:value-of select="format-number(PixelPercent1, '##.##')"/></td>
         </xsl:when>
         <xsl:when test="PixelPercent1 &lt; '5'">
           <td bgcolor="#DDDD22"><xsl:value-of select="format-number(PixelPercent1, '##.##')"/></td>
         </xsl:when>
         <xsl:otherwise>
           <td bgcolor="#DD2222"><xsl:value-of select="format-number(PixelPercent1, '##.##')"/></td>
         </xsl:otherwise>
       </xsl:choose>
       </tr>
       <tr>
       <!-- <td><xsl:value-of select="TestcaseID"/></td> -->
       <td><p><xsl:value-of select="Name"/></p><p align="center">End Frame</p></td>
       <td><a href="{BaseLine2}"><img src="{BaseLine2}" width="150" height="100"/></a></td>
       <td><a href="{Capture2}"><img src="{Capture2}" width="150" height="100"/></a></td>
       <td><a href="{Diff2}"><img src="{Diff2}" width="150" height="100"/></a></td>
       <xsl:choose>
         <xsl:when test="PixelPercent2 &lt; '1'">
           <td><xsl:value-of select="format-number(PixelPercent21, '##.##')"/></td>
         </xsl:when>
         <xsl:when test="PixelPercent2 &lt; '5'">
           <td bgcolor="#DDDD22"><xsl:value-of select="format-number(PixelPercent2, '##.##')"/></td>
         </xsl:when>
         <xsl:otherwise>
           <td bgcolor="#DD2222"><xsl:value-of select="format-number(PixelPercent2, '##.##')"/></td>
         </xsl:otherwise>
       </xsl:choose>
       </tr>

Any Ideas?

Sean

Posted (edited)

I need help with adding a reference to an external XSL file to the beginning of my XML file.

I have XML output using _XMLWrapper that looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<TestResult>
<TestCase>
<Name>scn01_1000Cubes_1view_Wireframe</Name>
<AvgTime>1700.82353181363</AvgTime>
<FPS>58.8</FPS>
<BaseLine1>baseline\scn01_1000Cubes_1view_Wireframe_begin.jpg</BaseLine1>
<BaseLine2>baseline\scn01_1000Cubes_1view_Wireframe_end.jpg</BaseLine2>
<Capture1>capture\scn01_1000Cubes_1view_Wireframe_begin.jpg</Capture1>
<Capture2>capture\scn01_1000Cubes_1view_Wireframe_end.jpg</Capture2>
<Diff1>diff\scn01_1000Cubes_1view_Wireframe_begin.jpg</Diff1>
<Diff2>diff\scn01_1000Cubes_1view_Wireframe_end.jpg</Diff2>
<PixelDiff1>189783</PixelDiff1>
<PixelPercent1>21.37</PixelPercent1>
<PixelDiff2>189783</PixelDiff2>
<PixelPercent2>21.37</PixelPercent2>
</TestCase>

I need to add this:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="result.xsl"?>
<TestResult>

Here is an example of the XSL file, which is formating the XML data out to an HTML table.

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

<xsl:template match="/">
 <html>
 <body>
   <h2>Softimge Certification Results</h2>

   <p></p>
   <table border="2">
    <tr>
    <td colspan="8" bgcolor="#ffcccc"><b><center>OpenGL</center></b></td>
    </tr>
     <tr bgcolor="#ffcccc">
       <!-- <th>TestcaseID</th> -->
       <th>Name</th>
       <th>Baseline</th>
       <th>ScreenCapture</th>
       <th>Comparison</th>
       <th>Difference</th>
       <th>Time</th>
       <th>Pass</th>
       <th>Status</th>
     </tr>
     <xsl:for-each select="TestResult/TestCase">
     <tr>
       <!-- <td><xsl:value-of select="TestcaseID"/></td> -->
       <td><p><xsl:value-of select="Name"/></p><p align="center">Begin Frame</p></td>
       <td><a href="{BaseLine1}"><img src="{BaseLine1}" width="150" height="100"/></a></td>
       <td><a href="{Capture1}"><img src="{Capture1}" width="150" height="100"/></a></td>
       <td><a href="{Diff1}"><img src="{Diff1}" width="150" height="100"/></a></td>
       <xsl:choose>
         <xsl:when test="PixelPercent1 &lt; '1'">
           <td><xsl:value-of select="format-number(PixelPercent1, '##.##')"/></td>
         </xsl:when>
         <xsl:when test="PixelPercent1 &lt; '5'">
           <td bgcolor="#DDDD22"><xsl:value-of select="format-number(PixelPercent1, '##.##')"/></td>
         </xsl:when>
         <xsl:otherwise>
           <td bgcolor="#DD2222"><xsl:value-of select="format-number(PixelPercent1, '##.##')"/></td>
         </xsl:otherwise>
       </xsl:choose>
       </tr>
       <tr>
       <!-- <td><xsl:value-of select="TestcaseID"/></td> -->
       <td><p><xsl:value-of select="Name"/></p><p align="center">End Frame</p></td>
       <td><a href="{BaseLine2}"><img src="{BaseLine2}" width="150" height="100"/></a></td>
       <td><a href="{Capture2}"><img src="{Capture2}" width="150" height="100"/></a></td>
       <td><a href="{Diff2}"><img src="{Diff2}" width="150" height="100"/></a></td>
       <xsl:choose>
         <xsl:when test="PixelPercent2 &lt; '1'">
           <td><xsl:value-of select="format-number(PixelPercent21, '##.##')"/></td>
         </xsl:when>
         <xsl:when test="PixelPercent2 &lt; '5'">
           <td bgcolor="#DDDD22"><xsl:value-of select="format-number(PixelPercent2, '##.##')"/></td>
         </xsl:when>
         <xsl:otherwise>
           <td bgcolor="#DD2222"><xsl:value-of select="format-number(PixelPercent2, '##.##')"/></td>
         </xsl:otherwise>
       </xsl:choose>
       </tr>

Any Ideas?

Sean

If I understand correctly, you created the xml file using the wrapper. So what you need is to add a processing instruction to the xml. At present, there is not a function built in to create the node. I will work one up shortly and possibly one for properties. Mean while you can add this code after the call to _XMLCreateFile().

$objPI= $objDoc.createProcessingInstruction('xml-stylesheet','type="text/xsl" href="result.xsl"')
$objDoc.AppendChild($objPI)
_XMLSaveDoc()
$objPI = 0

You can load the xml with the wrapper , create the processing instruction and save the xml. The processing instruction will be at the end of the xml though. I don't know how that will effect the output of the transform. It seem that the style sheet is cut off, so I could not try it.

Edit: If you have control over the stylesheet, you can have it add the instruction:

<xsl:processing-instruction name="xml-stylesheet">type="text/xsl" href="result.xsl"</xsl:processing-instruction>

Where in the code it goes, I don't know.

Edited by eltorro
Posted

If I understand correctly, you created the xml file using the wrapper. So what you need is to add a processing instruction to the xml. At present, there is not a function built in to create the node. I will work one up shortly and possibly one for properties. Mean while you can add this code after the call to _XMLCreateFile().

$objPI= $objDoc.createProcessingInstruction('xml-stylesheet','type="text/xsl" href="result.xsl"')
$objDoc.AppendChild($objPI)
_XMLSaveDoc()
$objPI = 0

You can load the xml with the wrapper , create the processing instruction and save the xml. The processing instruction will be at the end of the xml though. I don't know how that will effect the output of the transform. It seem that the style sheet is cut off, so I could not try it.

Edit: If you have control over the stylesheet, you can have it add the instruction:

<xsl:processing-instruction name="xml-stylesheet">type="text/xsl" href="result.xsl"</xsl:processing-instruction>

Where in the code it goes, I don't know.

Using the code you provided above, I modified the _xmlcreatefile command:

Func _XMLCreateFile($strPath, $strRoot, $bOverwrite = False, $bUTF8 = False, $xslRef = 0, $ver = -1)
    Local $retval, $fe, $objPI, $objDoc, $rootElement, $propStrArray
    $fe = FileExists($strPath)
    If $fe And Not $bOverwrite Then
        $retval = (MsgBox(4097, "File Exists:", "The specified file exits." & @CRLF & "Click OK to overwrite file or cancel to exit."))
        If $retval = 1 Then
            FileCopy($strPath, $strPath & @YEAR & "-" & @MON & "-" & @MDAY & "_" & @HOUR & "-" & @MIN & "-" & @SEC & ".bak", 1)
            FileDelete($strPath)
            $fe = False
        Else
            _XMLError("Error failed to create file: " & $strPath & @CRLF & "File exists.")
            SetError(4)
            Return -1
        EndIf
    Else
        FileCopy($strPath, $strPath & ".old", 1)
        FileDelete($strPath)
        $fe = False
    EndIf
    If $fe = False Then
        If $ver <> -1 Then
            If $ver > -1 And $ver < 7 Then
                $objDoc = ObjCreate("Msxml2.DOMdocument." & $ver & ".0")
                If IsObj($objDoc) Then
                    $DOMVERSION = $ver
                EndIf
            Else
                MsgBox(266288, "Error:", "Failed to create object with MSXML version " & $ver)
                SetError(3)
                Return 0
            EndIf
        Else
            For $x = 8 To 0 Step - 1
                If FileExists(@SystemDir & "\msxml" & $x & ".dll") Then
                    $objDoc = ObjCreate("Msxml2.DOMdocument." & $x & ".0")
                    If IsObj($objDoc) Then
                        $DOMVERSION = $x
                        ExitLoop
                    EndIf
                EndIf
            Next
        EndIf
        If Not IsObj($objDoc) Then
            Return SetError(2)
        EndIf
        If $bUTF8 Then
            $objPI = $objDoc.createProcessingInstruction ("xml", "version=""1.0"" encoding=""UTF-8""")
        Else
            $objPI = $objDoc.createProcessingInstruction ("xml", "version=""1.0""")
        EndIf
        $objDoc.appendChild ($objPI)
    ;testcode
        
        If Not IsNumber($xslRef) then
        
            $objPI = $objDoc.createProcessingInstruction ('xml-stylesheet', 'type="text/xsl" href="'&$xslRef&'"')
            $objDoc.AppendChild($objPI)
            
    ;   _XMLSaveDoc()
    ;   $objPI = 0
        EndIf
    ;testcode_end
        $rootElement = $objDoc.createElement ($strRoot)
        $objDoc.documentElement = $rootElement
        $objDoc.save ($strPath)
        If $objDoc.parseError.errorCode <> 0 Then
            _XMLError("Error Creating specified file: " & $strPath)
            SetError($objDoc.parseError.errorCode)
            Return -1
        EndIf
        Return 1
    Else
        _XMLError("Error! Failed to create file: " & $strPath)
        SetError(1)
        Return 0
    EndIf
    Return 1
EndFunc  ;==>_XMLCreateFile

This allows for me to pass a FileName to the $xslRef argument in _XMLCreateFile and to generate the proper statement. It appears at the top of the file just under the XML header info. Works perfectly for me, but may lack a certain elegance. I tried creating a more generic structure that could format other xml properties, but wasn't successful and since this did what I needed, I stopped here.

Thanks for your help, I would have never figured out the structure otherwise.

Sean

  • 3 weeks later...
Posted

I get the same error I got with another code, here is all of it, it will only read/write to the first node..

$Path = "//Keys"
            $NodesArray = _XMLGetChildNodes($Path)
            $Go = 0
            If $Proceed = 1 Then
                Do
                    For $x = 1 To $NodesArray[0] And $Proceed = 1
                        $CheckKey = CheckKey(_XMLGetAttrib($Path & "/Key[" & $x & "]", "SpellID"))
                        If $CheckKey = -1 Then
                            MsgBox(16, "Error", "Unable to read process memory!")
                            $Proceed = 0
                        EndIf
                        If $Bar <> "" Then
                            $GetStatus = StringSplit($Bar, "|")
                            If $GetStatus[0] = 2 Then
                                If $CheckKey = 1 Then
                                    _XMLSetAttrib($Path & "/Key[" & $x & "]", "BarState", $GetStatus[1])
                                    MsgBox(0, "Test", $GetStatus[1] & " written to node " & $x)
                                    _XMLSetAttrib($Path & "/Key[" & $x & "]", "Char", $GetStatus[2])
                                    MsgBox(0, "Test", $GetStatus[2] & " written to node " & $x)
                                EndIf
                            EndIf
                        EndIf

                        $msg = GUIGetMsg()
                        If $msg = -3 Then
                            Exit
                        EndIf
                        If $Proceed = 1 Then
                            $Go = $Go + 100 / $NodesArray[0]
                            GUICtrlSetData($Progress, $Go)
                        EndIf
                        If $Go >= 100 Then
                            MsgBox(0, "Done", "Done")
                            GUICtrlSetData($Progress, 0)
                        EndIf
                    Next
                Until $Go >= 100 Or $Proceed = 0
            EndIf
Posted (edited)

Heya ^^

I think it's amazing that eltorro is still helping us noobs with his script :D

I had some questions on page 18, and now im back her on 22. Again, my problem is about the "[]" when getting the values from an xml-file. This time i'm dealing with a script with only only a root (called "keys") and a lot of childnodes holding different values! What my script does is to arrange these and put in comments so that it will be easily readible.

The xml-file is the Keys.xml from the bot "mmoGlider" for World of Warcraft atm. holding about 500 childnodes (different keys and attributes for each of these).

Here is a part of the file:

<Key KeyName="Warlock.ConsumeShadows" BarState="Indifferent" ShiftState="Ctrl" Char="6" />
    <Key KeyName="Warlock.Corruption" BarState="Combat" ShiftState="None" Char="3" />
    <Key KeyName="Warlock.CreateHealthstone" BarState="Rest" ShiftState="None" Char="0" />
    <Key KeyName="Warlock.Curse" BarState="Combat" ShiftState="None" Char="2" />
    <Key KeyName="Warlock.DarkPact" BarState="Rest" ShiftState="None" Char="3" />
    <Key KeyName="Warlock.Deathcoil" BarState="Rest" ShiftState="None" Char="o" />
    <Key KeyName="Warlock.DemonArmor" BarState="Rest" ShiftState="None" Char="4" />
    <Key KeyName="Warlock.DrainLife" BarState="Combat" ShiftState="None" Char="5" />
    <Key KeyName="Warlock.DrainSoul" BarState="Combat" ShiftState="None" Char="6" />
    <Key KeyName="Warlock.Fear" BarState="Combat" ShiftState="None" Char="8" />
    <Key KeyName="Warlock.HealthFunnel" BarState="Rest" ShiftState="None" Char="7" />
    <Key KeyName="Warlock.Immolate" BarState="Combat" ShiftState="None" Char="4" />
    <Key KeyName="Warlock.Lifetap" BarState="Combat" ShiftState="None" Char="1" />
    <Key KeyName="Warlock.Reckless" BarState="Combat" ShiftState="None" Char="7" />
    <Key KeyName="Warlock.Shadowbolt" BarState="Combat" ShiftState="None" Char="9" />
    <Key KeyName="Warlock.SoulLink" BarState="Rest" ShiftState="None" Char="3" />
    <Key KeyName="Warlock.SpellLock" BarState="Indifferent" ShiftState="Ctrl" Char="6" />
    <Key KeyName="Warlock.Suffering" BarState="Indifferent" ShiftState="Ctrl" Char="7" />
    <Key KeyName="Warlock.SummonDemon" BarState="Rest" ShiftState="None" Char="5" />
    <Key KeyName="Warlock.UseHealthstone" BarState="Combat" ShiftState="None" Char="0" />
    <Key KeyName="Warlock.VoidieSacrifice" BarState="Indifferent" ShiftState="Ctrl" Char="5" />
    <Key KeyName="Warlock.Wand" BarState="Combat" ShiftState="None" Char="p" />

As you can see, this is quite unreadable... This is what I want to get:

<!-- Bar1, Combat -->
    <Key KeyName="LL.DrainLife" BarState="Bar1" ShiftState="None" Char="1" />
    <Key KeyName="LL.CurseOfAgony" BarState="Bar1" ShiftState="None" Char="2" />
    <Key KeyName="LL.Corruption" BarState="Bar1" ShiftState="None" Char="3" />
    <Key KeyName="LL.Lifetap" BarState="Bar1" ShiftState="None" Char="4" />
    <Key KeyName="LL.DrainSoul" BarState="Bar1" ShiftState="None" Char="5" />
    <Key KeyName="LL.Immolate" BarState="Bar1" ShiftState="None" Char="6" />
    <Key KeyName="LL.Fear" BarState="Bar1" ShiftState="None" Char="7" />
    <Key KeyName="LL.SiphonLife" BarState="Bar1" ShiftState="None" Char="8" />
    <Key KeyName="LL.ShadowBolt" BarState="Bar1" ShiftState="None" Char="9" />
    <Key KeyName="LL.UseHealthstone" BarState="Bar1" ShiftState="None" Char="0" />
    <Key KeyName="LL.DrainMana" BarState="Bar1" ShiftState="None" Char="o" />
    <Key KeyName="LL.Wand" BarState="Bar1" ShiftState="None" Char="p" />

<!-- Bar3 -->
    <Key KeyName="LL.SoulLink" BarState="Bar3" ShiftState="None" Char="1" />
    <Key KeyName="LL.DarkPact" BarState="Bar3" ShiftState="None" Char="2" />
    <Key KeyName="LL.FelDomination" BarState="Bar3" ShiftState="None" Char="3" />
    <!-- 4 FREE -->
    <Key KeyName="LL.DemonicSacrifice" BarState="Bar3" ShiftState="None" Char="5" />
    <Key KeyName="LL.CurseOfRecklessness" BarState="Bar3" ShiftState="None" Char="6" />
    <Key KeyName="LL.UnstableAffliction" BarState="Bar3" ShiftState="None" Char="7" />
    <Key KeyName="LL.AmplifyCurse" BarState="Bar3" ShiftState="None" Char="8" />
    <!-- 9 HealthPotion -->
    <!-- 0 ManaPotion -->
    <Key KeyName="LL.DeathCoil" BarState="Bar3" ShiftState="None" Char="o" />
    <Key KeyName="LL.BloodFury" BarState="Bar3" ShiftState="None" Char="p" />

<!-- Bar6, Rest -->
    <!-- 1 FOOD -->
    <!-- 2 DRINK -->
    <Key KeyName="LL.SummonImp" BarState="Bar6" ShiftState="None" Char="3" />
    <Key KeyName="LL.SummonVoidwalker" BarState="Bar6" ShiftState="None" Char="4" />
    <Key KeyName="LL.SummonSuccubus" BarState="Bar6" ShiftState="None" Char="5" />
    <Key KeyName="LL.SummonFelhunter" BarState="Bar6" ShiftState="None" Char="6" />
    <Key KeyName="LL.SummonFelguard" BarState="Bar6" ShiftState="None" Char="7" />
    <Key KeyName="LL.HealthFunnel" BarState="Bar6" ShiftState="None" Char="8" />
    <!-- 9 Mount -->
    <Key KeyName="LL.CreateHealthstone" BarState="Bar6" ShiftState="None" Char="0" />
    <Key KeyName="LL.ArmorBuff" BarState="Bar6" ShiftState="None" Char="o" />
    <!-- p Hearthstone -->

<!-- Petbar -->
    <Key KeyName="LL.VoidwalkerSacrifice" BarState="Indifferent" ShiftState="Ctrl" Char="5" />
    <Key KeyName="LL.ConsumeShadows" BarState="Indifferent" ShiftState="Ctrl" Char="6" />

To arrange the kays like this, I need to get the values for each of the keys. They will be arranged by "KeyName", "BarState" and "Char".

The problem I then have is: My script first collects the number of childnodes from "//Keys/*". This should make it possible for it to store all the values as follows:

#include <GUIConstants.au3>
#include <_XMLDomWrapper.au3>
#include <Array.au3>

_SetDebug(True)

_XMLFileOpen("Keys.xml")

$nodes = _XMLGetNodeCount("//Keys/*")

$test = _XMLGetChildNodes("//Keys")

$KeyNumber = 123;;Just an example... should be the key currently going through formatting...

msgbox(1,$nodes, $test[$KeyNumber]);;the msgbox is also just a quick test to see if i can get the different nodenames

but it seems like I can't use variables inside the []s

Edited by some1
Posted

Hi,

I'm just trying your UDF for the first time to hopefully help with an issue I have. I have a bunch of xml documents (sometimes thousands) and I need to be able to scan each file and get a date from one of the sections. I'm enumerating the xml files ok and getting those in an array, then against each file I'm running your function to try to get the value but it is not working, it is returning a -1 and an @error of 1. Not sure why?

Below is the code and an example of one of the xml files. The xml didn't paste too well into the post though but these are standard validate xml files.

Thanks,

Terry

#include <_XMLDomWrapper.au3>
#include <Array.au3>
#include <File.au3>

$Path = "C:\temp\test"
$LOG = "C:\temp\READXML.txt"

; Scan Machine for files
$List = _FileListToArray($Path, "*", 1)

For $x = 1 To $List[0]
    
    $ret = _XMLFileOpen ($List[$x])
    
    If $ret = 0 Then Exit

    $Return = _XMLGetValue( "//Files/ModifiedDate") ;/Dataroot/Files/ModifiedDate

    _FileWriteToLine($LOG, 0, $Return, 0)

    Exit
    
Next

#cs XML File Shown below.  Doesn't seem to paste well?
  <?xml version="1.0" encoding="UTF-8" ?> 
- <dataroot>
- <WordProperties>
- <FileID>
- <![CDATA[ {0A35A1B9-6765-463D-94CF-E9077A927F28}
  ]]> 
  </FileID>
  <HaveVersions>False</HaveVersions> 
  </WordProperties>
- <VBAProperties>
- <FileID>
- <![CDATA[ {0A35A1B9-6765-463D-94CF-E9077A927F28}
  ]]> 
  </FileID>
  <NoVBAProject>1</NoVBAProject> 
  <CertIssuedBy /> 
  <CertIssuedTo /> 
  <CertSerialNum /> 
  <CertValidFrom /> 
  <CertValidTo /> 
  <SigTimeStampSigningTime /> 
  <SigTimeStampSignerName /> 
  </VBAProperties>
- <Files>
- <ScanID>
- <![CDATA[ {FF5076C2-3CBD-4648-B500-AE53874B7491}
  ]]> 
  </ScanID>
- <FileID>
- <![CDATA[ {0A35A1B9-6765-463D-94CF-E9077A927F28}
  ]]> 
  </FileID>
- <FileName>
- <![CDATA[ IE4 security zones-lab.doc
  ]]> 
  </FileName>
- <FilePath>
- <![CDATA[ \\dept03\glp_archive\Technical Support P Taylor\Technical Support\Publications\2-Ready for tech writers
  ]]> 
  </FilePath>
- <ShortFilePath>
- <![CDATA[ \\dept03\glp_archive\techni~1\techni~1\public~1\2-read~1
  ]]> 
  </ShortFilePath>
- <FileExtension>
- <![CDATA[ doc
  ]]> 
  </FileExtension>
  <FileFormatID>7</FileFormatID> 
- <ModifiedDate>
- <![CDATA[ 1999-07-27 17:14:04
  ]]> 
  </ModifiedDate>
- <CreatedDate>
- <![CDATA[ 2005-09-21 16:19:06
  ]]> 
  </CreatedDate>
  <IsReadOnly>0</IsReadOnly> 
  <FileSize>35840</FileSize> 
- <FileOwner>
- <![CDATA[ SEATTLE\darren
  ]]> 
  </FileOwner>
  <HashCode>1506905510</HashCode> 
  <CSIDL>-1</CSIDL> 
  </Files>
  </dataroot>
#ce

As you can see I'm trying to write the modified date section from each xml file to a log file so I can review.

Thanks,

Terry

Posted

Never mind, I figured it out. The array being returned was just the file name not the full path to the XML. Arrgg.. plus I had an exit in a bad place.

Thanks for the UDF seems to work great now.

Terry

Posted

Heya ^^

I think it's amazing that eltorro is still helping us noobs with his script :D

I had some questions on page 18, and now im back her on 22. Again, my problem is about the "[]" when getting the values from an xml-file. This time i'm dealing with a script with only only a root (called "keys") and a lot of childnodes holding different values! What my script does is to arrange these and put in comments so that it will be easily readible.

The xml-file is the Keys.xml from the bot "mmoGlider" for World of Warcraft atm. holding about 500 childnodes (different keys and attributes for each of these).

Here is a part of the file:

<Key KeyName="Warlock.ConsumeShadows" BarState="Indifferent" ShiftState="Ctrl" Char="6" />
    <Key KeyName="Warlock.Corruption" BarState="Combat" ShiftState="None" Char="3" />
    <Key KeyName="Warlock.CreateHealthstone" BarState="Rest" ShiftState="None" Char="0" />
    <Key KeyName="Warlock.Curse" BarState="Combat" ShiftState="None" Char="2" />
    <Key KeyName="Warlock.DarkPact" BarState="Rest" ShiftState="None" Char="3" />
    <Key KeyName="Warlock.Deathcoil" BarState="Rest" ShiftState="None" Char="o" />
    <Key KeyName="Warlock.DemonArmor" BarState="Rest" ShiftState="None" Char="4" />
    <Key KeyName="Warlock.DrainLife" BarState="Combat" ShiftState="None" Char="5" />
    <Key KeyName="Warlock.DrainSoul" BarState="Combat" ShiftState="None" Char="6" />
    <Key KeyName="Warlock.Fear" BarState="Combat" ShiftState="None" Char="8" />
    <Key KeyName="Warlock.HealthFunnel" BarState="Rest" ShiftState="None" Char="7" />
    <Key KeyName="Warlock.Immolate" BarState="Combat" ShiftState="None" Char="4" />
    <Key KeyName="Warlock.Lifetap" BarState="Combat" ShiftState="None" Char="1" />
    <Key KeyName="Warlock.Reckless" BarState="Combat" ShiftState="None" Char="7" />
    <Key KeyName="Warlock.Shadowbolt" BarState="Combat" ShiftState="None" Char="9" />
    <Key KeyName="Warlock.SoulLink" BarState="Rest" ShiftState="None" Char="3" />
    <Key KeyName="Warlock.SpellLock" BarState="Indifferent" ShiftState="Ctrl" Char="6" />
    <Key KeyName="Warlock.Suffering" BarState="Indifferent" ShiftState="Ctrl" Char="7" />
    <Key KeyName="Warlock.SummonDemon" BarState="Rest" ShiftState="None" Char="5" />
    <Key KeyName="Warlock.UseHealthstone" BarState="Combat" ShiftState="None" Char="0" />
    <Key KeyName="Warlock.VoidieSacrifice" BarState="Indifferent" ShiftState="Ctrl" Char="5" />
    <Key KeyName="Warlock.Wand" BarState="Combat" ShiftState="None" Char="p" />

As you can see, this is quite unreadable... This is what I want to get:

<!-- Bar1, Combat -->
    <Key KeyName="LL.DrainLife" BarState="Bar1" ShiftState="None" Char="1" />
    <Key KeyName="LL.CurseOfAgony" BarState="Bar1" ShiftState="None" Char="2" />
    <Key KeyName="LL.Corruption" BarState="Bar1" ShiftState="None" Char="3" />
    <Key KeyName="LL.Lifetap" BarState="Bar1" ShiftState="None" Char="4" />
    <Key KeyName="LL.DrainSoul" BarState="Bar1" ShiftState="None" Char="5" />
    <Key KeyName="LL.Immolate" BarState="Bar1" ShiftState="None" Char="6" />
    <Key KeyName="LL.Fear" BarState="Bar1" ShiftState="None" Char="7" />
    <Key KeyName="LL.SiphonLife" BarState="Bar1" ShiftState="None" Char="8" />
    <Key KeyName="LL.ShadowBolt" BarState="Bar1" ShiftState="None" Char="9" />
    <Key KeyName="LL.UseHealthstone" BarState="Bar1" ShiftState="None" Char="0" />
    <Key KeyName="LL.DrainMana" BarState="Bar1" ShiftState="None" Char="o" />
    <Key KeyName="LL.Wand" BarState="Bar1" ShiftState="None" Char="p" />

<!-- Bar3 -->
    <Key KeyName="LL.SoulLink" BarState="Bar3" ShiftState="None" Char="1" />
    <Key KeyName="LL.DarkPact" BarState="Bar3" ShiftState="None" Char="2" />
    <Key KeyName="LL.FelDomination" BarState="Bar3" ShiftState="None" Char="3" />
    <!-- 4 FREE -->
    <Key KeyName="LL.DemonicSacrifice" BarState="Bar3" ShiftState="None" Char="5" />
    <Key KeyName="LL.CurseOfRecklessness" BarState="Bar3" ShiftState="None" Char="6" />
    <Key KeyName="LL.UnstableAffliction" BarState="Bar3" ShiftState="None" Char="7" />
    <Key KeyName="LL.AmplifyCurse" BarState="Bar3" ShiftState="None" Char="8" />
    <!-- 9 HealthPotion -->
    <!-- 0 ManaPotion -->
    <Key KeyName="LL.DeathCoil" BarState="Bar3" ShiftState="None" Char="o" />
    <Key KeyName="LL.BloodFury" BarState="Bar3" ShiftState="None" Char="p" />

<!-- Bar6, Rest -->
    <!-- 1 FOOD -->
    <!-- 2 DRINK -->
    <Key KeyName="LL.SummonImp" BarState="Bar6" ShiftState="None" Char="3" />
    <Key KeyName="LL.SummonVoidwalker" BarState="Bar6" ShiftState="None" Char="4" />
    <Key KeyName="LL.SummonSuccubus" BarState="Bar6" ShiftState="None" Char="5" />
    <Key KeyName="LL.SummonFelhunter" BarState="Bar6" ShiftState="None" Char="6" />
    <Key KeyName="LL.SummonFelguard" BarState="Bar6" ShiftState="None" Char="7" />
    <Key KeyName="LL.HealthFunnel" BarState="Bar6" ShiftState="None" Char="8" />
    <!-- 9 Mount -->
    <Key KeyName="LL.CreateHealthstone" BarState="Bar6" ShiftState="None" Char="0" />
    <Key KeyName="LL.ArmorBuff" BarState="Bar6" ShiftState="None" Char="o" />
    <!-- p Hearthstone -->

<!-- Petbar -->
    <Key KeyName="LL.VoidwalkerSacrifice" BarState="Indifferent" ShiftState="Ctrl" Char="5" />
    <Key KeyName="LL.ConsumeShadows" BarState="Indifferent" ShiftState="Ctrl" Char="6" />

To arrange the kays like this, I need to get the values for each of the keys. They will be arranged by "KeyName", "BarState" and "Char".

The problem I then have is: My script first collects the number of childnodes from "//Keys/*". This should make it possible for it to store all the values as follows:

#include <GUIConstants.au3>
#include <_XMLDomWrapper.au3>
#include <Array.au3>

_SetDebug(True)

_XMLFileOpen("Keys.xml")

$nodes = _XMLGetNodeCount("//Keys/*")

$test = _XMLGetChildNodes("//Keys")

$KeyNumber = 123;;Just an example... should be the key currently going through formatting...

msgbox(1,$nodes, $test[$KeyNumber]);;the msgbox is also just a quick test to see if i can get the different nodenames
but it seems like I can't use variables inside the []s

This isn't exactly what you want, but you should be able to get there from here.

#include <GUIConstants.au3>
#include <_XMLDomWrapper.au3>
#include <Array.au3>

_XMLFileOpen("Keys.xml")

$nodes = _XMLGetNodeCount("//Keys/*")
If $nodes =0 then
    MsgBox(0,"Error","No nodes found")
    Exit
EndIf

For $x =1 to $nodes
    $msg = "" 
    Local $aName[1],$aValue[1]
    _XMLGetAllAttrib('//Keys/*[ @BarState="Rest" and position()='&$x&']', $aName,$aValue)
    If UBound($aName)> 1 Then
        For $y = 0 to UBound($aName)-1
            $msg &= StringFormat("%d: %s \t %s\r\n",$x,$aName[$y],$aValue[$y])
        Next
        MsgBox(0,"Key "&$x,$msg)
    EndIf
Next
  • 2 weeks later...
Posted (edited)

Hi, I am trying to extract data from a Garmin training database.

I want to get contents of all <Trackpoint> nodes, which are nested in several <Lap> and <Track> nodes. I don't care which lap and track they are in, I only want the trackpoints.

Can I use the wildcard (*) halfway down the path in stead of walking through all the occurrences of the lap and track nodes? Example: //activities/*/*/Trackpoint/Time

Edited by Avee
Posted

I don't have this program so inherently I do not have the necessary XML file for testing. If you could provide an example we could try to come up with something.

Posted (edited)

Here's a part of the xml.

My goal is to fill arrays with all the timestamps, distances, elevations and heart rates. Regardless what activity, lap or track they are in. I could first get all activities, laps and tracks and then walk through all of them, but is there an easier way to just "disregard" those nodes in between?

<?xml version="1.0" encoding="UTF-8" standalone="no" ?> 
- <TrainingCenterDatabase xmlns="http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2 http://www.garmin.com/xmlschemas/TrainingCenterDatabasev2.xsd">
- <Activities>
 - <Activity Sport="Biking">
   <Id>2007-09-03T19:03:43Z</Id> 
  - <Lap StartTime="2007-09-03T19:03:43Z">
    <TotalTimeSeconds>5309.7300000</TotalTimeSeconds> 
    <DistanceMeters>18821.4882813</DistanceMeters> 
    <MaximumSpeed>15.5050001</MaximumSpeed> 
    <Calories>1450</Calories> 
   - <AverageHeartRateBpm xsi:type="HeartRateInBeatsPerMinute_t">
     <Value>155</Value> 
     </AverageHeartRateBpm>
   - <MaximumHeartRateBpm xsi:type="HeartRateInBeatsPerMinute_t">
     <Value>190</Value> 
     </MaximumHeartRateBpm>
     <Intensity>Active</Intensity> 
     <TriggerMethod>Manual</TriggerMethod> 
   - <Track>
    - <Trackpoint>
      <Time>2007-09-03T19:03:43Z</Time> 
    - <Position>
       <LatitudeDegrees>39.0886344</LatitudeDegrees> 
       <LongitudeDegrees>-84.4688488</LongitudeDegrees> 
      </Position>
      <AltitudeMeters>185.6717529</AltitudeMeters> 
      <DistanceMeters>0.0000000</DistanceMeters> 
    - <HeartRateBpm xsi:type="HeartRateInBeatsPerMinute_t">
       <Value>182</Value> 
      </HeartRateBpm>
      <SensorState>Absent</SensorState> 
     </Trackpoint>
   - <Trackpoint>
      <Time>2007-09-03T19:03:44Z</Time> 
    - <Position>
       <LatitudeDegrees>39.0886227</LatitudeDegrees> 
       <LongitudeDegrees>-84.4687664</LongitudeDegrees> 
      </Position>
      <AltitudeMeters>185.1911621</AltitudeMeters> 
      <DistanceMeters>7.4052925</DistanceMeters> 
    - <HeartRateBpm xsi:type="HeartRateInBeatsPerMinute_t">
       <Value>182</Value> 
      </HeartRateBpm>
      <SensorState>Absent</SensorState> 
     </Trackpoint>
Edited by Avee
Posted

This XML stuff drives me crazy!

$var = _XMLGetChildNodes(".") returns "TrainingCenterDatabase" ($var[1])

Next I try

$var = _XMLGetChildNodes("/TrainingCenterDatabase") which causes "No Matching Nodes found"

$var = _XMLGetChildNodes("//TrainingCenterDatabase") same problem

Why??? If I prefix // it should look through the whole file for this node right? So why does it return a node as a child of the current node (root I guess), but doesn't find anything when I prefix //?

To fill all timestamps in the file into an array like I desribed before, shouldn't a

$var = _XMLGetValue("//Trackpoint/Time")

do the trick? Doesn't return an array, just -1!

Posted

Solved it myself. It was the namespace. I was succesful with following code

; Open input file
$TcxFile = _XMLFileOpen($TcxFileName, 'xmlns:xsl="http://www.w3.org/1999/XSL/Transform" ' & _
    'xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:fo="http://www.w3.org/1999/XSL/Format" ' & _
    'xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" '& _
    'xmlns:tcx="http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2"')
If @error Then
    MsgBox(16, "Filesystem Error", "Unable to open tcx file.")  
    Exit
EndIf

;Here the arrays get filled with values from the xml file
$TimeStampArray = _XMLGetValue("//tcx:Trackpoint/tcx:Time")
$DistanceArray = _XMLGetValue("//tcx:Trackpoint/tcx:DistanceMeters")
$AltitudeArray = _XMLGetValue("//tcx:Trackpoint/tcx:AltitudeMeters")
$HeartRateArray = _XMLGetValue("//tcx:Trackpoint/tcx:HeartRateBpm/tcx:Value")

Thanks for the XML Library!

Posted (edited)

Ok, stupid question time. How can I add a child node using an XPATH, when there are many that are the same?

<project>
  <file>
    <name>thisfile.ext</name>
  </file>
  <file>
    <name>thatfile.ext</name>
  </file>
  <file>
    <name>somefile.ext</name>
  </file>
</project>

If I want to build the above, I can't just use '/Project/File', because that adds it to all of them.

Is there some way to get the path to the last node, or to specify a node by it's index?

Edit: SOLVED: /project/file[last()]

Thanks to W3Schools

Edited by aGorilla

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...