Leaderboard
Popular Content
Showing content with the highest reputation on 09/03/2022 in all areas
-
You already have a solution, but using an xpath can be like this: $xpathMonthlyCharges = "//div/label[.='Monthly Charges:']/../div/div" #region SCITE_CallTipsForFunctions ;BGe_IEGetDOMObjByXPathWithAttributes($oIEObj, $sXPath, [$iMaxWait=2000]) Return array of objects on browser matching callers xpath #endregion SCITE_CallTipsForFunctions #include <ie.au3> #include <array.au3> #region GLOBALVariables Global $gbBGe_PerformConsoleWrites = False ; The XPath array to work with will be 2d, with the following Global Enum $giBGe_XPath_Dim2_sRawNode, _ $giBGe_XPath_Dim2_sNodeName, _ $giBGe_XPath_Dim2_bNodeIsRelative, _ $giBGe_XPath_Dim2_sRawNodeConstraints, _ $giBGe_XPath_Dim2_bIsConstrainted, _ $giBGe_XPath_Dim2_aNodeConstraints, _ $giBGe_XPath_Dim2_UBound ; $giBGe_XPath_Dim2_aNodeConstraints will contain a 2d, with the following Global Enum $giBGe_Constraint_Dim2_sNodeName, _ $giBGe_Constraint_Dim2_bIsAttribute, _ $giBGe_Constraint_Dim2_bIsSelf, _ $giBGe_Constraint_Dim2_sNodeValue, _ $giBGe_Constraint_Dim2_bIsContains, _ $giBGe_Constraint_Dim2_UBound ; Regexp to split xpath Global $gsBGe_RegExpNodeSplit = "(?U)(.*(?:['""].*['""].*){0,})(?:\/)" ; Split Xpath into nodes...split by / where it is part of x-path Global $gsBGe_RegExpNodeAndCondSplit = "([^\[\]]+)\[(.*)\]" ; Get node name and conditions...conditions can be empty Global $gsBGe_RegExpOrSplit = "(?i)(?U)(.*['""].*['""\)])(?:\sor\s)|.{1,}?" ; Split Or statements inside [] Global $gsBGe_RegExpAndSplit = "(?i)(?U)(.*['""].*['""\)])(?:\sand\s)|.{1,}?" ; Split And statements inside [] Global $gsBGe_RegExpSplitContains = "(?i)contains\s*\(\s*(.+)\s*,\s*['""](.+)['""]\s*\)" ; Split contains, remove spaces that are not needed Global $gsBGe_RegExpSplitNonContains = "(.*)\s*\=\s*['""](.*)['""]" ; Split constraint that is not a contains, remove spaces that are not needed #endregion GLOBALVariables #region SAMPLE $xpathMonthlyCharges = "//div/label[.='Monthly Charges:']/../div/div" ; Create/navigate to page $oIE = _IECreate("",True,True) If IsObj($oIE) Then ConsoleWrite("Able to _IECreate('')" & @CRLF) Else ConsoleWrite("UNable to _IECreate('')" & @CRLF) Exit 1 EndIf _IEBodyWriteHTML($oIE,'<div class="box-header"> <div class="title"> Account Summary </div> </div> <div class="box-content box-overflow-fix"> <div class="form-group"> <label class="col-xs-2 control-label">Previous Account Balance:</label> <div class="col-xs-1"> <div id="previous-account-balance" class="form-control-static currency"> 203.39 </div> </div> </div> <div class="form-group"> <label class="col-xs-2 control-label">Monthly Charges:</label> <div class="col-xs-1"> <div class="form-control-static currency"> 87.80 </div> </div> </div> <div class="form-group"> <label class="col-xs-2 control-label">One Time Charges:</label> <div class="col-xs-1"> <div class="form-control-static currency"> 0.00 </div> </div> </div> <div class="form-group"> <label class="col-xs-2 control-label">Call Usage:</label> <div class="col-xs-1"> <div class="form-control-static currency"> 0.00 </div> </div> </div> <div class="form-group"> <label class="col-xs-2 control-label">Hosted Fax Usage:</label> <div class="col-xs-1"> <div class="form-control-static currency"> 0.00 </div> </div> </div> <div class="form-group"> <label class="col-xs-2 control-label">Directory Assistance:</label> <div class="col-xs-1"> <div class="form-control-static currency"> 0.00 </div> </div> </div> <div class="form-group"> <label class="col-xs-2 control-label">Taxes and Fees:</label> <div class="col-xs-1"> <div id="taxes-fees" class="form-control-static currency"> 5.13 </div> </div> </div> <div class="form-group"> <label class="col-xs-2 control-label">Total New Charges - Due 8/30/2022:</label> <div class="col-xs-1"> <div id="total-new-charges" class="form-control-static currency"> 02.93 </div> </div> </div> <div class="form-group"> <label class="col-xs-2 control-label">Total Due:</label> <div class="col-xs-1"> <div id="total-due" class="form-control-static currency"> 306.32 </div> </div> </div> </div> </div>') ; Get Forum Link $aForumLink = BGe_IEGetDOMObjByXPathWithAttributes($oIE,$xpathMonthlyCharges,0) For $i = 0 to UBound($aForumLink)-1 ConsoleWrite("text = " & $aForumLink[$i].innertext & @CRLF) Next _IEQuit($oIE) Exit #endregion SAMPLE #region ExternalFunctions Func BGe_IEGetDOMObjByXPathWithAttributes($oIEObject, $sXPath, $iMaxWait=2000) ; Get dom object by XPath If $gbBGe_PerformConsoleWrites Then ConsoleWrite("Start Function=[BGe_IEGetDOMObjByXPathWithAttributes] with $sXPath=[" & $sXPath & "]." & @CRLF) Local $aReturnObjects = "" Local $aSplitXpath = BGe_ParseXPath($sXPath) If Not IsArray($aSplitXpath) Then ConsoleWrite("BGe_IEGetDOMObjByXPathWithAttributes: Callers XPath/Node/Conditions not well formed=[" & $sXPath & "]" & @CRLF) Return SetError(1,0,False) EndIf Local $iTimer = TimerInit() Do $aReturnObjects = BGe_RecursiveGetObjWithAttributes($oIEObject,$aSplitXpath) Until TimerDiff($iTimer)>$iMaxWait Or IsArray($aReturnObjects) Return $aReturnObjects EndFunc ;==>BGe_IEGetDOMObjByXPathWithAttributes #endregion ExternalFunctions #region InternalFunctions Func BGe_RecursiveGetObjWithAttributes($oParent, $aCallersSplitXPath, $asHolder="", $Level=0) $asObjects = $asHolder Local $sNodeName = $aCallersSplitXPath[$Level][$giBGe_XPath_Dim2_sNodeName] Local $bNodeIsRelative = $aCallersSplitXPath[$Level][$giBGe_XPath_Dim2_bNodeIsRelative] ; true=relative false=absolute Local $bIsConstrainted = $aCallersSplitXPath[$Level][$giBGe_XPath_Dim2_bIsConstrainted] ; array[OR] of arrays[AND]; all constraints on the node Local $aNodeOrConstraints = $aCallersSplitXPath[$Level][$giBGe_XPath_Dim2_aNodeConstraints] ; array[OR] of arrays[AND]; all constraints on the node Local $aPossibleNodeMatch = "" If $gbBGe_PerformConsoleWrites Then ConsoleWrite("Start Function=[BGe_RecursiveGetObjWithAttributes] level=[" & $Level & "]: $sNodeName=[" & $sNodeName & "], $bNodeIsRelative=[" & $bNodeIsRelative & "] $bIsConstrainted=[" & $bIsConstrainted & "]."& @CRLF) If Not IsObj($oParent) Then Return $asObjects ; Get nodes that match If $bNodeIsRelative Then If $sNodeName = "*" Then $oPossibleNodes = _IETagNameAllGetCollection($oParent) Else $oPossibleNodes = _IETagNameGetCollection($oParent, $sNodeName) EndIf For $oPossibleNode In $oPossibleNodes If $oPossibleNode.NodeType == 1 Then ; only add nodes If IsArray($aPossibleNodeMatch) Then _ArrayAdd($aPossibleNodeMatch,$oPossibleNode) Else Local $aPossibleNodeMatch[1] = [$oPossibleNode] EndIf EndIf Next ElseIf $sNodeName = ".." Then $asObjects = BGe_RecursiveGetObjWithAttributes($oParent.parentNode, $aCallersSplitXPath, $asObjects, $Level + 1) Else $oPossibleNodes = $oParent.childnodes For $oPossibleNode In $oPossibleNodes If String($oPossibleNode.NodeName) = $sNodeName Or $sNodeName = "*" Then If IsArray($aPossibleNodeMatch) Then _ArrayAdd($aPossibleNodeMatch,$oPossibleNode) Else Local $aPossibleNodeMatch[1] = [$oPossibleNode] EndIf EndIf Next EndIf ; Loop through nodes against restraints If IsArray($aPossibleNodeMatch) Then For $iChild = 0 To UBound($aPossibleNodeMatch) - 1 Local $oChild = $aPossibleNodeMatch[$iChild] ; Find matching conditions, when necessary If $bIsConstrainted Then ; Loop through OR Conditions For $i = 0 To UBound($aNodeOrConstraints) - 1 Local $aNodeAndConstraints = $aNodeOrConstraints[$i] Local $bAndConditionsMet = True ; Loop through And Conditions, or conditions are outside of this loop, and will go if current and's are not met For $j = 0 To UBound($aNodeAndConstraints) - 1 ; Remove the @... Local $sConstraintName = StringReplace($aNodeAndConstraints[$j][$giBGe_Constraint_Dim2_sNodeName],"@","") Local $bConstraintIsAtt = $aNodeAndConstraints[$j][$giBGe_Constraint_Dim2_bIsAttribute] Local $bConstraintIsNode = $aNodeAndConstraints[$j][$giBGe_Constraint_Dim2_bIsSelf] Local $sConstraintValue = $aNodeAndConstraints[$j][$giBGe_Constraint_Dim2_sNodeValue] Local $bConstraintIsContains= $aNodeAndConstraints[$j][$giBGe_Constraint_Dim2_bIsContains] If $bConstraintIsNode Then If $bConstraintIsContains Then If Not StringInStr(String($oChild.innertext), $sConstraintValue) Then $bAndConditionsMet = False Else If String($oChild.innertext) <> $sConstraintValue Then $bAndConditionsMet = False EndIf ElseIf $bConstraintIsAtt Then Local $sAttributeValue = "" Switch $sConstraintName Case "class" $sAttributeValue = $oChild.className() Case "style" $sAttributeValue = $oChild.style.csstext Case "onclick" $sAttributeValue = $oChild.getAttributeNode($sConstraintName).value Case Else $sAttributeValue = $oChild.getAttribute($sConstraintName) EndSwitch If $bConstraintIsContains Then If Not StringInStr(String($sAttributeValue), $sConstraintValue) Then $bAndConditionsMet = False Else If String($sAttributeValue) <> $sConstraintValue Then $bAndConditionsMet = False EndIf Else ; failure EndIf ; Skip looping if a condition of the And array was not met If Not $bAndConditionsMet Then ExitLoop Next If $bAndConditionsMet Then ; If last level, add the object If $Level = UBound($aCallersSplitXPath) - 1 Then If Not IsArray($asObjects) Then Local $asObjects[1]=[$oChild] Else $bUnique = True ; Only add if not present in the array For $iObject = 0 To UBound($asObjects)-1 If $oChild = $asObjects[$iObject] Then $bUnique=False ExitLoop EndIf Next If $bUnique Then _ArrayAdd($asObjects, $oChild) EndIf Else $asObjects = BGe_RecursiveGetObjWithAttributes($oChild, $aCallersSplitXPath, $asObjects, $Level + 1) EndIf EndIf ; No need to loop additional or if already found one and If $bAndConditionsMet Then ExitLoop Next Else ; No constraints, match is implied If $Level = UBound($aCallersSplitXPath) - 1 Then ; Final xpath level, so add to final array If Not IsArray($asObjects) Then Local $asObjects[1]=[$oChild] Else Local $bUnique=True ; Only add if not present in the array For $iObject = 0 To UBound($asObjects)-1 If $oChild = $asObjects[$iObject] Then $bUnique=False ExitLoop EndIf Next If $bUnique Then _ArrayAdd($asObjects, $oChild) EndIf Else ; Continue Recurssion $asObjects = BGe_RecursiveGetObjWithAttributes($oChild, $aCallersSplitXPath, $asObjects, $Level + 1) EndIf EndIf Next EndIf Return $asObjects EndFunc ;==>BGe_RecursiveGetObjWithAttributes Func BGe_ParseXPath($sCallersXPath) ; RegExp require a trailing "/" $sCallersXPath &= "/" Local $aReturnParsedXPath=False ; Parse all the '/' outside of single, or double, quotes Local $aNodesWithQualifiers = StringRegExp($sCallersXPath,$gsBGe_RegExpNodeSplit,3) ; Loop through, and determine if the node is direct, or relative.../ vs // Local $iSlashCount = 0 For $i = 0 To UBound($aNodesWithQualifiers) - 1 If StringLen($aNodesWithQualifiers[$i])=0 Then $iSlashCount+=1 Else ; Add dimentions to the return array If Not IsArray($aReturnParsedXPath) Then Local $aReturnParsedXPath[1][$giBGe_XPath_Dim2_UBound] Else ReDim $aReturnParsedXPath[UBound($aReturnParsedXPath)+1][$giBGe_XPath_Dim2_UBound] EndIf $aReturnParsedXPath[UBound($aReturnParsedXPath)-1][$giBGe_XPath_Dim2_sRawNode] = $aNodesWithQualifiers[$i] ; Split current Node Local $aSplitNodeAndCond = StringRegExp($aNodesWithQualifiers[$i],$gsBGe_RegExpNodeAndCondSplit,3) If UBound($aSplitNodeAndCond) = 2 Then Local $sNodeName = $aSplitNodeAndCond[0] Local $sNodeConstraints = $aSplitNodeAndCond[1] $aNodeConstraints = BGe_ParseXPathConstraints($sNodeConstraints) If Not IsArray($aNodeConstraints) Then ConsoleWrite("ParseXPath: Callers XPath/Node/Conditions not well formed=[" & $aNodesWithQualifiers[$i] & "]" & @CRLF) Return SetError(1,1,False) EndIf ElseIf UBound($aSplitNodeAndCond) = 0 Then Local $sNodeName = $aNodesWithQualifiers[$i] Local $sNodeConstraints = "" Local $aNodeConstraints = "" Else ConsoleWrite("ParseXPath: Callers XPath/Node/Conditions not well formed=[" & $aNodesWithQualifiers[$i] & "]" & @CRLF) Return SetError(1,2,False) EndIf $aReturnParsedXPath[UBound($aReturnParsedXPath)-1][$giBGe_XPath_Dim2_sNodeName] = $sNodeName $aReturnParsedXPath[UBound($aReturnParsedXPath)-1][$giBGe_XPath_Dim2_sRawNodeConstraints] = $sNodeConstraints $aReturnParsedXPath[UBound($aReturnParsedXPath)-1][$giBGe_XPath_Dim2_bIsConstrainted] = (StringLen($sNodeConstraints)>0) $aReturnParsedXPath[UBound($aReturnParsedXPath)-1][$giBGe_XPath_Dim2_aNodeConstraints] = $aNodeConstraints $aReturnParsedXPath[UBound($aReturnParsedXPath)-1][$giBGe_XPath_Dim2_bNodeIsRelative] = $iSlashCount>1 $iSlashCount=1 EndIf Next Return $aReturnParsedXPath EndFunc Func BGe_ParseXPathConstraints($sCallersXPathConstraints) ; Returns array of arrays ; Array is split of all 'or' statements, and then includes array of 'and' statements, which are split out into 2d array of name/value/bcontains Local $aReturnParsedXPathConstraints[1] ; Will always return at least the first condition Local $aOrQualifiers = StringRegExp($sCallersXPathConstraints,$gsBGe_RegExpOrSplit,3) ReDim $aReturnParsedXPathConstraints[UBound($aOrQualifiers)] For $i = 0 To UBound($aReturnParsedXPathConstraints)-1 Local $aAndQualifiers = StringRegExp($aOrQualifiers[$i],$gsBGe_RegExpAndSplit,3) Local $aaSplitQualitfiers = BGe_ParseXPathConstraint($aAndQualifiers) If IsArray($aaSplitQualitfiers) Then $aReturnParsedXPathConstraints[$i]=$aaSplitQualitfiers Else ConsoleWrite("ParseXPathConstraints: Callers XPath/Node/Conditions not well formed=[" & $aOrQualifiers[$i] & "]" & @CRLF) Return SetError(1,3,False) EndIf Next Return $aReturnParsedXPathConstraints EndFunc Func BGe_ParseXPathConstraint($aCallersXPathConstraint) Local $aReturnParsedXPathConstraints[UBound($aCallersXPathConstraint)][$giBGe_Constraint_Dim2_UBound] For $i = 0 To UBound($aCallersXPathConstraint)-1 ; Remove leading and trailing spaces Local $sCurrentConstraint = StringStripWS($aCallersXPathConstraint[$i], 3) ; Check if $sCurrentConstraint makes use of contains() Local $aTempContains = StringRegExp($sCurrentConstraint,$gsBGe_RegExpSplitContains,3) Local $aTempNonContains = StringRegExp($sCurrentConstraint,$gsBGe_RegExpSplitNonContains,3) If UBound($aTempContains)=2 Then $aReturnParsedXPathConstraints[$i][$giBGe_Constraint_Dim2_bIsContains] = True $aReturnParsedXPathConstraints[$i][$giBGe_Constraint_Dim2_bIsSelf] = ($aTempContains[0]=".") $aReturnParsedXPathConstraints[$i][$giBGe_Constraint_Dim2_sNodeName] = $aTempContains[0] $aReturnParsedXPathConstraints[$i][$giBGe_Constraint_Dim2_bIsAttribute] = (StringLeft($aTempContains[0],1)="@") $aReturnParsedXPathConstraints[$i][$giBGe_Constraint_Dim2_sNodeValue] = $aTempContains[1] ElseIf UBound($aTempNonContains)=2 And Not StringInStr($aTempNonContains[0],"(") Then $aReturnParsedXPathConstraints[$i][$giBGe_Constraint_Dim2_bIsContains] = False $aReturnParsedXPathConstraints[$i][$giBGe_Constraint_Dim2_bIsSelf] = ($aTempNonContains[0]=".") $aReturnParsedXPathConstraints[$i][$giBGe_Constraint_Dim2_sNodeName] = $aTempNonContains[0] $aReturnParsedXPathConstraints[$i][$giBGe_Constraint_Dim2_bIsAttribute] = (StringLeft($aTempNonContains[0],1)="@") $aReturnParsedXPathConstraints[$i][$giBGe_Constraint_Dim2_sNodeValue] = $aTempNonContains[1] Else ConsoleWrite("ParseXPathConstraint: Callers XPath/Node/Conditions not well formed=[" & $aCallersXPathConstraint[$i] & "]" & @CRLF) Return SetError(1,4,False) EndIf Next Return $aReturnParsedXPathConstraints EndFunc #endregion InternalFunctions consoleoutput: text = 87.801 point
-
The basic parts are there 1 lexer for the input 2 parse for the visual output It will depend on the requirements how much time it will take and if you want a pure autoit version or parse the output in https://graphviz.org/ layout https://en.m.wikipedia.org/wiki/DOT_(graph_description_language)1 point
-
DEMO VIDEO DBUG demo Update 4, files are changed! 28-jan-2010 - new buttons for debugging and managing the expressions list (add, delete, save, restore) - button images - pause button - mouse over variable names in the source code displays the current variable value as tooltip! Features - Debug the complete script or just parts of it - Display run status (linenumber of currently executed function) - GUI default always-on-top in the upper right corner for comfortable debugging - WM_NOTIFY and WM_COMMAND hook to prevent interference with possible message handlers - Display scope, type and value of variables, expressions, macro's and constants (global AND function local) - Execute commands in an immediate window. Can be expressions, functions and assignments - Detailed display of array, struct and object variables - Dynamic display of variable value in the source code (under cursor) Useage 1) #include <dbug.au3> as first line of the script to debug (after placing dbug.au3 in the include folder of course) 2) copy the images in a folder IMAGES on the same level as the Include folder 3) run the script! That's all. Take special care when debugging message handlers, when they don't return fast enough, strange things may happen. To prevent this, you may add a line ;STOP DBUG before the part you want to exclude from debugging until the line ;START DBUG (or the end of the script). Update 3, files are changed! Extended to debug complete scripts, not just lines. Update2 Although the GUI looks the same, the script is completely rewritten. Changes: - More reliable: debugger doesn't fail on constants and not declared variables. - No limitation to the count of variables that are read. - Determination of variable scope is correct. - Indication of breakpoint line when used with SciTE. - Re-entry of the debugger is prevented and indicated. Update Damn, I found a serious flaw in the script. The basic idea is to Execute() a function with the local variables as arguments. To be changable at debug time they are passed ByRef. This works wonderfull for variables but when constants are passed then the Execute() fails silently. I don't see how I can prevent this, anybody any idea? Original post Hi Gents, when playing with AutoIt I felt the need of an easy way to debug a bit more sophisticated then endless adding msgbox and consolewrites to my scripts. After looking around I start thinking of a way to make local variables visible outside there scope and came up with Dbug.au3. It's far from perfect but I wanted to share with you. Hope to hear your comments and maybe you find it usefull. By now the features are: - display scope, type and value of variables, expressions, macro's and constants (global AND function local) - execute commands in an immediate window. Can be expressions, functions and assignments - detailed display of array, struct and object variables - set a breakpoint expression Limitations are there also: - max 20 variables to display - scope display is not as reliable as it should be - when there is a not declared variable in the debugged function, debugging fails without an errormessage (Opt('MustDeclareVars', 1) helps) - multiple debug windows not allowed (but who does need them anyway?) - and without doubt more not yet discovered bugs! Examples: display: binary($var), @scriptdir, $var_a & $var_b, $arr[1][2], timerinit(), etc commands: $a = $b, ($c >= $d), $struc, $arr[3][4] = 'testDBUG', StringRegExp('TestDBUG', 'D(.*)', 2), etc, etc Usage: - Include the debug script dbug.au3 in the script you want to debug. - Write Execute(_debug()) on every line you want to inspect. - That's all! To play right away I supplied a little test script too (TestDBUG.au3) Files: dbug.au3 - debug script (Update 3 downloads: 94) IMAGES - Folder with fancy button images TestDBUG.au3 - declaration of some variables and calls to debugger I really like to know what you think of it and if you can use it. I spent far more time on it then planned So feedback is appreciated! IMAGES.ZIP Dbug.au3 TestDBUG.au31 point