coles Posted February 18, 2019 Posted February 18, 2019 (edited) Hi All, Need a help with Autoit task, I am trying to copy an XML file and edit that XML file and copy it back The script i have attached if the script we use to copy files to client from server, so basically what it does is Going through a Set of IP address and Map the drive Copy the file Write copy process was success Goes on a loop through IP's to check all machines have updated files expandcollapse popup#include <File.au3> #include <iNet.au3> #include <_XMLDomWrapper.au3> func latestUpdate($address, $name) Local $result Local $hFileIndexHTML DriveMapDel ( "G:" ) ConsoleWrite('Trying: ' & $address & "/" & $name & @CRLF); $result = DriveMapAdd ( "G:", "\\" & $address & "\C$", 0, $name & "\adminname","adminpswd") ;Copying the file from Mapped drive to local if $result = 1 Then FileCopy( "G:\Program Files\test.xml", "C:\sample\test.xml", 1); ConsoleWrite('Copying Updated File: ' & $address & @CRLF); $hFileIndexHTML = FileOpen("C:\sample\test.txt", 1) FileWrite($hFileIndexHTML, $address & @CRLF) FileClose($hFileIndexHTML) EndIf EndFunc func done($file, $address) For $i = 1 to _FileCountLines($file) $line = FileReadLine($file, $i) if ( $address = $line ) Then ConsoleWrite('Already done: ' & $file & " " & $address & @CRLF); return true EndIf Next return false EndFunc func getMachineName($ipaddress) return _TCPIpToName($ipaddress) EndFunc func process($address) local $machineName $machineName = getMachineName($address) if ($machineName = "") Then ConsoleWrite("No machine found at:" & $address & @CRLF) Else ConsoleWrite("Machine found at:" & $address & " - " & $machineName & @CRLF) if ( done( "C:\sample\test.txt", $address) = false ) then if ( $machineName <> "" ) then latestUpdate($address, $machineName) else endif endif EndIf EndFunc TCPStartup() while 1=1 PROCESS("10.10.1.1") sleep( 1000 * 60 * 10) wend The XML file i am trying to copy is unique and different in all machines (Machine name,ID's etc), But whole structure is the same (ie, the num of lines ) [That's the reason i can't copy a single file to all the machines]. I was thinking of using _FileWriteToLine to replace 3 lines with new data eg: _FileWriteToLine("c:\sample\test.xml", 71, "<RIA>"http://goog.html"</RIA>", True) _FileWriteToLine("c:\sample\test.xml", 350, "<col header="Status" width="7%" dataFld="status_code" style="" preprocesser="processES" template="" hidden="0"/>", True) _FileWriteToLine("c:\sample\test.xml", 650, "<col header="Units" width="11%" dataFld="units" style="" preprocesser="" template="fU(units)" hidden="0"/>", True) These lines inside XML 340<em> 341<gd 342-360 is similar as blah blah <col header="Status" width="7%" dataFld="status_code" style="" preprocesser="processES" template="" hidden="0"/> same goes for 650th line also I would like to get opinion of copying this file as this is a highly critical file needed to keep machines running Do you think using _file write to line is risky?. Do you think i have to copy the file from parent folder to another folder after replacing the lines and then copy from there back to client system. This is all what i can think now, Any comments/suggestions will be much appreciated. Edited February 18, 2019 by coles Missed out few words
Subz Posted February 18, 2019 Posted February 18, 2019 If you check the number of lines of the target.xml are the same as the source.xml the _FileWriteToLine method should be fine, if they don't have the same number of lines just write to a network share that they aren't equal and you can check on these machines at a later stage. One note you would have to enclose those _FileWriteToLine lines with single quote ' at the beginning and end, as the lines you posted would error because of the internal double quotes. I would also backup the target.xml file before making changes, something like: FileCopy("<Path to Target.xml", @LocalAppDataDir & "\Backup\Target.xml", 8) that way you can restore the file if it fails. Alternatively you could use XML Dom which I see you have included in your script and then just use _XMLSetAttrib to change the code. coles 1
coles Posted February 18, 2019 Author Posted February 18, 2019 Thank you @Subz for the quick reply. Yes i have checked the number of lines of both target and source, both are same. Thanks for that tip regarding Single quote as i was having trouble initially. Easiest code i can think of is FileCopy( "G:\Program Files\test.xml", "C:\sample\test.xml", 1); -FileWritetoline... -FileWritetoline... -FileWritetoline... Sleep(2000) FileCopy( "C:\sample\test.xml", "G:\Program Files\test.xml", 1); ConsoleWrite('Copying Updated File: ' & $address & @CRLF); $hFileIndexHTML = FileOpen("C:\sample\test.txt", 1) FileWrite($hFileIndexHTML, $address & @CRLF) FileClose($hFileIndexHTML) This works perfectly fine and functioning as needed. Only thing is now i think about the source file, it may not be same in all machines. As i might have edited may be 5-10% of them every now and then with no thoughts about such a need will arise in the future. Is there a way where the text change's can be made to the xml file to those specific lines, irrespective of the line number. Any help will be appreciated
FrancescoDiMuro Posted February 18, 2019 Posted February 18, 2019 @coles Could you post a sample "source" file and the result you are expecting from your script? coles 1 Click here to see my signature: Spoiler ALWAYS GOOD TO READ: Forum Rules Forum Etiquette
coles Posted February 18, 2019 Author Posted February 18, 2019 @FrancescoDiMuro Hi i am adding a sample of source file. what i am expecting from my script is changes in line 71 existing[<ReferenceInformationAction>"C:\Program Files\Internet Explorer\iexplore.exe" -k "c:\temp\temp.html"</ReferenceInformationAction>] to [<ReferenceInformationAction>"C:\Program Files\Internet Explorer\iexplore.exe" -k "http:\\10.1.1.1\temp.html"</ReferenceInformationAction>] Line 375 existing[<col header="Location" width="30%" dataFld="location" style="" preprocesser="" template="formatUnitLocation(location, unid)" hidden="1"/>]to[<col header="Location" width="30%" dataFld="location" style="" preprocesser="" template="formatUnitLocation(location, unid)" hidden="0"/>] Line 376 existing [<col header="DGroup" width="10%" dataFld="dgroup" style="" preprocesser="" template="" hidden="0"/>] to [<col header="DGroup" width="10%" dataFld="dgroup" style="" preprocesser="" template="" hidden="1"/>] at the moment with the above script [in orginal post & reply to subz] i am able to change by over writing the specific lines. Looking for a dynamic approach to do the changes by not depending on the line numbers. Sample.xml
Subz Posted February 19, 2019 Posted February 19, 2019 You could use something like: expandcollapse popup#include <_XMLDomWrapper.au3> Global $g_bSaveXml = False Global $g_sSample = @ScriptDir & "\sample.xml" Global $g_sRefNode = '//mobilePublicSafety/settings/customparam/ReferenceInformationAction' Global $g_sLocNode = '//mobilePublicSafety/settings/monitors/unitMonitor/grid/col[@dataFld="location"]' Global $g_sDGrNode = '//mobilePublicSafety/settings/monitors/unitMonitor/grid/col[@dataFld="dgroup"]' _XMLFileOpen($g_sSample, "", -1, False) Switch @error Case 1 MsgBox(16, "XML File Open Error", 'An error occurred while attempting to parse ' & @CRLF & $g_sSample) Exit Case 2 MsgBox(16, "XML File Open Error", 'No object was found while attempting to parse ' & @CRLF & $g_sSample) Exit EndSwitch Local $oRefNode = $objDoc.selectSingleNode($g_sRefNode) If IsObj($oRefNode) Then Local $sRefNode = $oRefNode.Text If $sRefNode = '"C:\Program Files\Internet Explorer\iexplore.exe" -k "c:\temp\temp.html"' Then $oRefNode.Text = '"C:\Program Files\Internet Explorer\iexplore.exe" -k "http:\\10.1.1.1\temp.html"' $g_bSaveXml = True EndIf EndIf Local $oLocNode = $objDoc.selectSingleNode($g_sLocNode) If IsObj($oLocNode) Then Local $sLocNode = $oLocNode.getAttribute("hidden") If $sLocNode = 1 Then $oLocNode.setAttribute("hidden", 0) $g_bSaveXml = True EndIf EndIf Local $oDGrNodeNode = $objDoc.selectSingleNode($g_sDGrNode) If IsObj($oDGrNodeNode) Then Local $sDRgNode = $oDGrNodeNode.getAttribute("hidden") If $sDRgNode = 0 Then $oDGrNodeNode.setAttribute("hidden", 1) $g_bSaveXml = True EndIf EndIf If $g_bSaveXml Then $objDoc.Save("sample.xml") coles 1
coles Posted February 19, 2019 Author Posted February 19, 2019 @Subz Thank you so much for the effort to write it down and test it for me. I guess it was one of your sleepless bored nights , but really beneficial for me. Once again thanks for your help After going through help file just out of curiosity wanted to know, why you choose the above method. Instead of going with _ReplaceStringInFile
Subz Posted February 19, 2019 Posted February 19, 2019 NP Either method should work fine, but using xml dom is targeted whereas if there is one character out with _ReplaceStringInFile it will fail. Hope that made sense. coles 1
jdelaney Posted February 20, 2019 Posted February 20, 2019 (edited) XPaths can be made contextual too. Say you are attempting to replace a node value, but it's inside another node with some known attribute. You would have to reinvent the wheel to determine which child node to update with just a string replace; where with an xpath, you can do something like this to get the proper node: "//some/parent[@name='ThisIsTheParent']//child" There could be a million parent nodes, with unique name attributes, and you would be able to grab the child in one swoop rather than create complicated regular expressions or loops. Of course, there is a bit to the learning curve in creating well formed xpaths as well. Edited February 20, 2019 by jdelaney coles 1 IEbyXPATH-Grab IE DOM objects by XPATH IEscriptRecord-Makings of an IE script recorder ExcelFromXML-Create Excel docs without excel installed GetAllWindowControls-Output all control data on a given window.
coles Posted February 20, 2019 Author Posted February 20, 2019 Thank you @Subz, i didn't know that if a character was out of place _ReplaceStringInFile will fail. Thanks @jdelaney yes i will try more examples with well formed xpaths, so that next time it will be easier.
coles Posted February 21, 2019 Author Posted February 21, 2019 Thank you @Subz, i didn't know that if a character was out of place _ReplaceStringInFile will fail. Thanks @jdelaney yes i will try more examples with well formed xpaths, so that next time it will be easier. I would mark this topic as fixed, as @Subz solution have been working awesome for me. His way of getting the results were far better and dynamic than mine.
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now