0
votes

This is, I hope, a simple question but I can't see the wood for the trees.

The Delphi XML Data Binding Wizard was used some time ago to create a whole bunch of interfaces and classes for a hierarchical data set. Reading and writing the entire data set from and to an XML stream works well.

But now I want to be able to stream individual fragments of the data set. It doesn't matter whether it is valid according to any DTD for this purpose. I simply want a way to copy around individual fragments of the data set within the application, and reusing the existing XML streaming seemed a good idea. By a fragment, I mean a selection of sibling nodes in the data set (literally the selected nodes in a tree view) and all of their children.

To illustrate, to stream the entire data set I currently have, for each different type of object in the data set, a method like this:

procedure TPerson.Save(aXmlNode : IXMLNode);
var
  person : IXMLPersonType;
begin
  person := aXmlNode as IXMLPersonType;

  person.SetRate(fRate);

  for index := 0 to fTasks.Count - 1 do
  begin
    fTasks[index].Save(person.GetTasks.Add);
  end;

And to kick it all off:

procedure TProject.SaveProject;
var
  project : IXMLProjectType;
begin
  project := NewProject;
  Save(project);

All pretty standard stuff (I hope) if you've used the Data Binding Wizard before.

What I cannot now get my head around is how to kick things off if I just want to save a particular list of TPerson objects and downwards, rather than the whole project. Where do I get hold of the IXMLNode to pass into TPerson.Save? I'm lost in a maze of interfaces and classes generated by the wizard.

I've not got as far as reading the XML back in, but are there any further issues I need to worry about or will this bit be obvious?

(By the way I'd be happy(ish) with an answer stating that the Data Binding Wizard was not intended to be used with XML fragments so don't do it - if that is indeed the case.)

1

1 Answers

1
votes

AFAIK, there is no direct support for such operation, but you can do something like this (let assume iPerson represents a root element of a fragment):

var
  iPerson: IXMLNode;
  iFragment: IXMLNode;
  iNewDoc: IXMLDocument;
begin
  ...
  iFragment := iPerson.CloneNode(True);  // deep copy
  iNewDoc := NewXMLDocument;
  iNewDoc.DocumentElement := iFragment;
  iNewDoc.SaveToFile('C:\...\fragment.xml');
  ...

UPDATE: saving muliple siblings with mandatory root element e.g. like this:

iNewDoc := NewXMLDocument; 
iRoot := iNewDOC.CreateElement('persons',TargetNamespace); 
iNewDoc.DocumentElement := iRoot; 
for (...) do 
  begin 
    iFragment := iPersons.ChildNodes[i].CloneNode(True); // deep copy 
    iRoot.ChildNodes.Add(iFragment); 
  end; 
iNewDoc.SaveToFile('C:\...\siblings.xml');