Hello,
I'm using xmldoc for the first time to manage application data, because the ini files just dont have the structure. I was thinking about using a treeview style file with tabs, but that would be untidy and harder for people to work with.
The xml file is not set in stonde, and the program responds semi intellegently based on the configuration and entries.
I have two functions to access the file, getxmlval and setxmlval. My problem is that setxmlval isnt working.
Both work by a similar principle. they get passed a string that looks like this ..
node1.node1-1.node1-x.attribute_or_value
where node_x could be any number of nodes.
The functions drill into the xml file until they get to the last item in the string, and sees if its an attribute, node value, or if it exists at all.
my setxml code looks like this...
As a last resort I tried creating a pointer to the node I wanted to replace, but it dose not work.
If anyone else finds this useful, heres the code for getxml...
I hope someone can make use of this. I would love to hear from anyone with a solution to my setxml function problems.
All the best,
kinnon
I'm using xmldoc for the first time to manage application data, because the ini files just dont have the structure. I was thinking about using a treeview style file with tabs, but that would be untidy and harder for people to work with.
The xml file is not set in stonde, and the program responds semi intellegently based on the configuration and entries.
I have two functions to access the file, getxmlval and setxmlval. My problem is that setxmlval isnt working.
Both work by a similar principle. they get passed a string that looks like this ..
node1.node1-1.node1-x.attribute_or_value
where node_x could be any number of nodes.
The functions drill into the xml file until they get to the last item in the string, and sees if its an attribute, node value, or if it exists at all.
my setxml code looks like this...
Code:
// write to xml doc where path is parentnode.childnode.childnode....value/attr
procedure TForm1.setxmlval(path:String; Newval:Variant);
var sections:TStringList;
currnode:ixmlnode;
tn:^ixmlnode;
i: Integer;
begin
i:=0;
// break up the path sections by the dots into a string list
sections:=TStringList.Create;
sections.Text:=str_replace('.',^M,path,false);
// fetch the described xml value
xmldoc.FileName:=progdir+'wf.xml';
xmldoc.Active:=true;
currnode:=xmldoc.DocumentElement.ChildNodes.FindNode(sections.Strings[0]);// fetch the main node
tn^:=xmldoc.DocumentElement.ChildNodes.FindNode(sections.Strings[0]);
if sections.count>2 then
for i := 1 to sections.Count - 2 do
begin
currnode:=currnode.ChildNodes.FindNode(sections.Strings[i]);
tn^:=currnode.ChildNodes.FindNode(sections.Strings[i]);
end;
if i<=0 then i:=1;
if currnode<>nil then
begin
if xmlnodeexists(path) then
begin
// this is a node, not a preperty value
currnode.ChildValues[sections.Strings[i]]:=Newval;
xmldoc.Active:=true;
if xmldoc.Active=true then
begin
xmldoc.DocumentElement.ChildNodes.ReplaceNode(
xmldoc.DocumentElement.ChildNodes.FindNode(currnode.NodeName),
currnode);
xmldoc.savetofile(progdir+'wf2.xml');
end;
end
else
begin
// this is an attribute
currnode.SetAttribute(sections.strings[i],Newval);
xmldoc.Active:=true;
if xmldoc.Active=true then
begin
xmldoc.DocumentElement.ChildNodes.ReplaceNode(
currnode,tn^);
xmldoc.savetofile(progdir+'wf2.xml');
end;
end;
end
else
begin
log('node '+path+' not found!');
end;
log('Value of '+path+' is now '+vartostr(Newval));
sections.free;
end;
//setxml needs this to check if a node exists
function TForm1.xmlnodeexists(path:String):Boolean;
var sections:TStringList;
currnode:ixmlnode;
i: Integer;
begin
result:=false;
// break up the path sections by the dots
sections:=TStringList.Create;
sections.Text:=str_replace('.',^M,path,false);
if trim(sections.text)='-1' then sections.text:=path;
// fetch the described xml value
xmldoc.FileName:=progdir+'wf.xml';
xmldoc.Active:=true;
currnode:=xmldoc.DocumentElement.ChildNodes.FindNode(sections.Strings[0]);// fetch the main node
if sections.count>2 then
for i := 1 to sections.Count - 1 do
begin
currnode:=currnode.ChildNodes.FindNode(sections.Strings[i]);
end;
if currnode<>nil then
begin
result:=true;
end;
xmldoc.Active:=false;
end;
As a last resort I tried creating a pointer to the node I wanted to replace, but it dose not work.
If anyone else finds this useful, heres the code for getxml...
Code:
// read from an xml doc where path is parentnode.childnode.childnode....value/attr
function TForm1.getxmlval(path:String; Default:Variant):variant;
var sections:TStringList;
currnode:ixmlnode;
i: Integer;
begin
i:=0;
result:=Default;
// break up the path sections by the dots
sections:=TStringList.Create;
sections.Text:=str_replace('.',^M,path,false);
if trim(sections.text)='-1' then sections.text:=path;
// fetch the described xml value
xmldoc.FileName:=progdir+'wf.xml';
xmldoc.Active:=true;
currnode:=xmldoc.DocumentElement.ChildNodes.FindNode(sections.Strings[0]);// fetch the main node
if sections.count>2 then
for i := 1 to sections.Count - 2 do
begin
currnode:=currnode.ChildNodes.FindNode(sections.Strings[i]);
end;
if i<=0 then i:=1;
if currnode<>nil then
begin
result:=currnode.ChildValues[sections.Strings[i]];
if result=null then // if the value dosnt exist
begin
// check if the current section name is an attr
result:= currnode.GetAttribute(sections.Strings[i]);
end;
end
else
begin
log('node '+path+' not found!');
end;
if result=null then result:='';
log('Value of '+path+' is '+vartostr(result));
sections.free;
xmldoc.Active:=false;
end;
I hope someone can make use of this. I would love to hear from anyone with a solution to my setxml function problems.
All the best,
kinnon