Question

I am trying to change all instances of a number in an xml file. The constant 45 should be added to the number.

Temp is the following text:

<rownum value="1">
  <backupapplication>HP Data Protector</backupapplication>
  <policy>AUTDR12_Daily</policy>
  <policytype>FileSystem</policytype>
  <dataretained>31</dataretained>
  <fullbackup>7</fullbackup>
  <backuptime>0.17</backuptime>
  <retentionperiod>Short</retentionperiod>
  <peakmbps>11</peakmbps>
  <backupcategory>Fulls &amp; Fulls</backupcategory>
</rownum>
<rownum value="2">
  <backupapplication>HP Data Protector</backupapplication>
  <policy>AUTP_Appl_Monthly</policy>
  <policytype>FileSystem</policytype>
  <dataretained>268</dataretained>
  <fullbackup>91</fullbackup>
  <backuptime>2.31</backuptime>
  <retentionperiod>Long</retentionperiod>
  <peakmbps>12</peakmbps>
  <backupcategory>Fulls &amp; Fulls</backupcategory>
</rownum>

I tried the following code:

NeedleRegEx = <rownum value="(\d+)">
Replacement = <rownum value="($1+45)">
Temp := RegExReplace(Temp, NeedleRegEx, Replacement)

But this changes it into

<rownum value="1+45">

while I want

<rownum value="46">

How do I do this in AutoHotKey?

Was it helpful?

Solution

RegEx aren't designed to evaluate mathematical expressions. There are some languages, in which you can use a replacing function that can do dynamic replacements (e.g. JavaScript). But no such luck in AHK.
Using RegEx for the purpose of parsing XML documents isn't good practice anyway. I suggest using an XML parser instead. For AHK, you can utilize a COM object of MSXML2.DOMDocument. Here's an example (and further references) of how to use it: http://www.autohotkey.com/board/topic/56987-com-object-reference-autohotkey-v11/page-2#entry367838.
What you want to do is parse your XML to a DOM document and loop over every rownum tag. Now, you can retrieve the value attribute, increment it, and overwrite the attribute with the new value.

Update

To the code you've posted in the comments: There were some minor mistakes and one big mistake. The big mistake was trying to parse non-valid XML. You can check your XML files by feeding them to a formatter/validator. The loadXml()method will return false if there was a parsing error. The method obj.saveXML() does not exist. If you want to retrieve the document's string representation, simply access its xml property: obj.xml. If you want to save it to a file, there's the built-in method save(filepath).

Here's my suggestion for a clean approach (yes, you CAN use meaningful variable names!):

doc := ComObjCreate("MSXML2.DOMDocument.6.0")
if(!doc.loadXml(xmlString)) {
    msgbox % "Hey! That's no valid XML!"
    ExitApp
}

rownums := doc.getElementsByTagName("rownum")
Loop % rownums.length
{
    rownum := rownums.item(A_Index-1)
    value := rownum.getAttribute("value")
    value += 45
    rownum.setAttribute("value", value)
}

doc.save("myNewFile.xml")
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top