Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

XMLDoc ReplaceNode troubles

Status
Not open for further replies.

kinnon

Programmer
Dec 21, 2005
9
0
0
GB
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...

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
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top