Jump to content

How to read and update .xml by section key and value


Recommended Posts

            Hi everyone ,How to I can read and update type file .config.xml from secition key and value. I have many machines.

image.png.0d30c306113de391271af421b1474c32.png

                 Previously I can create script read update only .ini , I can do but for .xml i don't know how. Please guide me or give me ideas.

for my .xml as attched. Thank you

image.thumb.png.68773ed73b7877bba43ac512f898095c.png

 

FFIF_ProductSystemsSetting.config

Link to comment
Share on other sites

I have used RegEx for some light XML parsing for some work related stuff, and as long as it's valid, it seems to work well (for me). It's just a couple functions:

; <node ...> ... </node>
Func GetNode($xml, $node, $exact = True)
    Local $sExact
    If $exact = True Then
        $sExact = '(?:>|\s+?.*?>)'
    Else
        $sExact = '.*?>'
    EndIf

    Return StringRegExp($xml, '(?s)(<' & $node & $sExact & '.*?</' & $node & '>)', 3)
EndFunc   ;==>GetNode

; <node ... />
Func GetNode2($xml, $node, $exact = True)
    Local $sExact
    If $exact = True Then
        $sExact = '(?:/>|\s+?.*?/>)'
    Else
        $sExact = '.*?>'
    EndIf

    Return StringRegExp($xml, '(?s)(<' & $node & $sExact & ')', 3)
EndFunc   ;==>GetNode2

; <node ... attrib="xxx" ...>
Func GetAttrib($xml, $node, $attrib, $exact = True)
    Local $sExact
    If $exact = True Then
        $sExact = '\s+?.*?'
    Else
        $sExact = '.*?'
    EndIf

    $result = StringRegExp($xml, '(?i)<' & $node & $sExact & $attrib & '="(.*?)".*?>', 3)
    If Not @error Then Return $result[0]
    Return ''
EndFunc   ;==>GetAttrib

There may be some other solutions, such as something like this:

However my only experience with XML in AutoIt has been with the couple of functions above.

Also I suggest in the future that you post your code so that we can possibly select it to copy/paste and give it a shot ourselves: 

 

 

But, here's how I would use it to get the highlighted section of your code:

#include <String.au3>

Global $sXml = FileRead('FFIF_ProductSystemsSetting.config')
ConsoleWrite('$sXml length: ' & StringLen($sXml) & @CRLF)

Global $sConfigXml = GetNode($sXml, 'configuration', True)
If IsArray($sConfigXml) Then $sConfigXml = $sConfigXml[0]
ConsoleWrite('$sConfigXml length: ' & StringLen($sConfigXml) & @CRLF)

Global $sHoltXml = GetNode($sConfigXml, 'HOLTRX3_VL')
If IsArray($sHoltXml) Then $sHoltXml = $sHoltXml[0]
ConsoleWrite('$sHoltXml length: ' & StringLen($sHoltXml) & @CRLF)

Global $sCommonXml = GetNode($sHoltXml, 'Common')
If IsArray($sCommonXml) Then $sCommonXml = $sCommonXml[0]
ConsoleWrite('$sCommonXml length: ' & StringLen($sCommonXml) & @CRLF)

Global $sFFSServerVersion = GetAttrib($sCommonXml, 'add key="FFSServer"', 'value')
ConsoleWrite('FFSServer after traveling down the XML: ' & $sFFSServerVersion & @CRLF)

; Alternatively if there's just the one 'Common' node:
$sCommonXml = GetNode($sXml, 'Common')
If IsArray($sCommonXml) Then $sCommonXml = $sCommonXml[0]
ConsoleWrite('$sCommonXml length from $sXml direct: ' & StringLen($sCommonXml) & @CRLF)

; And if there's only going to be one instance of FFSServer node:
$sFFSServerVersion = GetAttrib($sXml, 'add key="FFSServer"', 'value')
ConsoleWrite('$sXml direct: ' & $sFFSServerVersion & @CRLF)

; And then the possibly simpler approach:
$sFFSServerVersion = _StringBetween($sXml, '"FFSServer" value="', '"')
If Not @error Then
    $sFFSServerVersion = $sFFSServerVersion[0]
    ConsoleWrite('_StringBetween: ' & $sFFSServerVersion & @CRLF)
EndIf


; <node ...> ... </node>
Func GetNode($xml, $node, $exact = True)
    Local $sExact
    If $exact = True Then
        $sExact = '(?:>|\s+?.*?>)'
    Else
        $sExact = '.*?>'
    EndIf

    Return StringRegExp($xml, '(?s)(<' & $node & $sExact & '.*?</' & $node & '>)', 3)
EndFunc   ;==>GetNode

; <node ... />
Func GetNode2($xml, $node, $exact = True)
    Local $sExact
    If $exact = True Then
        $sExact = '(?:/>|\s+?.*?/>)'
    Else
        $sExact = '.*?>'
    EndIf

    Return StringRegExp($xml, '(?s)(<' & $node & $sExact & ')', 3)
EndFunc   ;==>GetNode2

; <node ... attrib="xxx" ...>
Func GetAttrib($xml, $node, $attrib, $exact = True)
    Local $sExact
    If $exact = True Then
        $sExact = '\s+?.*?'
    Else
        $sExact = '.*?'
    EndIf

    $result = StringRegExp($xml, '(?i)<' & $node & $sExact & $attrib & '="(.*?)".*?>', 3)
    If Not @error Then Return $result[0]
    Return ''
EndFunc   ;==>GetAttrib

 

As you can see I accessed the data in a couple of ways, however the simplest way is probably going to be _StringBetween (https://www.autoitscript.com/autoit3/docs/libfunctions/_StringBetween.htm) or StringRegEx (https://www.autoitscript.com/autoit3/docs/functions/StringRegExp.htm

 

Edit: I missed the part about updating the XML, I haven't had a need to update an XML, so it again may be better to look into the XML UDF, or see if there's other solutions.

Edited by mistersquirrle

We ought not to misbehave, but we should look as though we could.

Link to comment
Share on other sites

I haven't had a need to update an XML, so it again may be better to look into the XML UDF, or see if there's other solutions.

However, without doing it in a "proper" way, you could just use StringReplace:

#include <FileConstants.au3>

Global $sFile = 'FFIF_ProductSystemsSetting.config'
Global $hFile = FileOpen($sFile, $FO_READ)
If $hFile = -1 Then
    ConsoleWrite('Unable to open file for writing' & @CRLF)
    Exit
EndIf
Global $sXml = FileRead($hFile)
FileClose($hFile)

$sXml = StringReplace($sXml, '"FFSServer" value="00.00.00.00"', '"FFSServer" value="01.01.01.01"')

$hFile = FileOpen($sFile, $FO_OVERWRITE)
If $hFile = -1 Then
    ConsoleWrite('Unable to open file for writing' & @CRLF)
    Exit
EndIf
FileWrite($hFile, $sXml)
FileClose($hFile)

You could also use my simple little XML functions to get the current value for FFSServer and use that in your StringReplace:

$sXml = StringReplace($sXml, '"FFSServer" value="' & $sValue & '"', '"FFSServer" value="01.01.01.01"')

 

We ought not to misbehave, but we should look as though we could.

Link to comment
Share on other sites

5 minutes ago, mistersquirrle said:

I haven't had a need to update an XML, so it again may be better to look into the XML UDF, or see if there's other solutions.

However, without doing it in a "proper" way, you could just use StringReplace:

#include <FileConstants.au3>

Global $sFile = 'FFIF_ProductSystemsSetting.config'
Global $hFile = FileOpen($sFile, $FO_READ)
If $hFile = -1 Then
    ConsoleWrite('Unable to open file for writing' & @CRLF)
    Exit
EndIf
Global $sXml = FileRead($hFile)
FileClose($hFile)

$sXml = StringReplace($sXml, '"FFSServer" value="00.00.00.00"', '"FFSServer" value="01.01.01.01"')

$hFile = FileOpen($sFile, $FO_OVERWRITE)
If $hFile = -1 Then
    ConsoleWrite('Unable to open file for writing' & @CRLF)
    Exit
EndIf
FileWrite($hFile, $sXml)
FileClose($hFile)

You could also use my simple little XML functions to get the current value for FFSServer and use that in your StringReplace:

$sXml = StringReplace($sXml, '"FFSServer" value="' & $sValue & '"', '"FFSServer" value="01.01.01.01"')

 

Appreciate for your help and give me for idea and example script. :)

Link to comment
Share on other sites

By using XMLDOM object, you get way more control on your XML files.  Here an example of how to use it :

#include <Constants.au3>

Local $oXML = ObjCreate("Microsoft.XMLDOM")
$oXML.load("FFIF_ProductSystemsSetting.config")
If $oXML.parseError.errorCode Then Exit MsgBox($MB_SYSTEMMODAL, "You have an error", $oXML.parseError.reason)

Local $oFFS = $oXML.SelectSingleNode("//configuration/HOLTRX3_VL/Common/add[@key='FFSServer']")
ConsoleWrite($oFFS.getAttribute('value') & @CRLF)
$oFFS.setAttribute('value', '192.191.12.99')
ConsoleWrite($oFFS.getAttribute('value') & @CRLF)
$oXML.save("FFIF New.config")

Complete reference is https://learn.microsoft.com/en-us/previous-versions/windows/desktop/ms764730(v=vs.85)

Link to comment
Share on other sites

12 minutes ago, Nine said:

By using XMLDOM object, you get way more control on your XML files.  Here an example of how to use it :

#include <Constants.au3>

Local $oXML = ObjCreate("Microsoft.XMLDOM")
$oXML.load("FFIF_ProductSystemsSetting.config")
If $oXML.parseError.errorCode Then Exit MsgBox($MB_SYSTEMMODAL, "You have an error", $oXML.parseError.reason)

Local $oFFS = $oXML.SelectSingleNode("//configuration/HOLTRX3_VL/Common/add[@key='FFSServer']")
ConsoleWrite($oFFS.getAttribute('value') & @CRLF)
$oFFS.setAttribute('value', '192.191.12.99')
ConsoleWrite($oFFS.getAttribute('value') & @CRLF)
$oXML.save("FFIF New.config")

Complete reference is https://learn.microsoft.com/en-us/previous-versions/windows/desktop/ms764730(v=vs.85)

Thank you very much this is new knowledge for me. :)

 

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...