Ok, here is an even more powerfull pair of UDF's ... it uses the XML path to read and write, much like a registry key path name. If the path one specifies doesn't exist, the UDF builds the path first, than pokes the value. Here's some examples:

$xmlFile = "e:\t.xml"

$= WriteXmlString($xmlFile, "form1/settings/left", 100)
$= WriteXmlString($xmlFile, "form1/settings/top", 200)

?"value=" ReadXmlString($xmlFile, "form1/settings/top")

[udf]
Code:

function WriteXmlString($filename, $path, $value)

dim $xmlDoc, $rootNode, $sectionNode;

$xmlDoc = CreateObject("Microsoft.XMLDOM");

if not $xmlDoc
return
endif

if not $xmlDoc.Load($filename)

$rootNode = $xmlDoc.createElement("configuration");
$= $xmlDoc.AppendChild($rootNode);

endif

$sectionNode = $xmlDoc.SelectSingleNode("/configuration/" + $path);

if not $sectionNode

$sectionNode = $xmlDoc.documentElement

for each $node in split($path,"/")

$childNode = $xmlDoc.CreateElement($node)

$= $sectionNode.AppendChild($childNode)

$sectionNode = $childNode

next

endif

$sectionNode.Text = $value;

$= $xmlDoc.Save($filename);

return

endfunction

function ReadXmlString($filename, $key, optional $defaultValue)

dim $xmlDoc, $sectionNode

$xmlDoc = CreateObject("Microsoft.XMLDOM")

if not $xmlDoc
return
endif

$= $xmlDoc.Load($filename)

$sectionNode = $xmlDoc.SelectSingleNode("/configuration/" + $key);

if not $sectionNode
$ReadXmlString = $defaultValue;
else
$ReadXmlString = $sectionNode.FirstChild.Text;
endif

endfunction