I don't seem to be able to iterate through the following XML file.
<?xml version="1.0" encoding="utf-8"?>
<Screen>
<Title>MainMenuScrn</Title>
<Start>True</Start>
<BackColor>clBlue</BackColor>
<Orientation>orLandscape</Orientation>
<Image><none></Image>
<tTFTImage>
<Enabled>True</Enabled>
<Fixed>False</Fixed>
<Height>57</Height>
<Image>HeatIcon</Image>
<Left>40</Left>
<Name>Image1</Name>
<Parent>pnlScreenArea</Parent>
<Top>49</Top>
<Visible>True</Visible>
<Width>57</Width>
</tTFTImage>
<tTFTStaticLabel>
<Caption>Settings</Caption>
<Enabled>True</Enabled>
<Fixed>False</Fixed>
<FontColor>clWhite</FontColor>
<FontRef>BigBold</FontRef>
<Height>16</Height>
<Left>237</Left>
<Name>StaticLabel3</Name>
<Parent>pnlScreenArea</Parent>
<Top>207</Top>
<Visible>True</Visible>
<Width>51</Width>
</tTFTStaticLabel>
<tTFTContainer>
<BorderStyle>bsNone</BorderStyle>
<Caption></Caption>
<Color>clYellow</Color>
<Enabled>True</Enabled>
<Height>138</Height>
<Left>59</Left>
<Name>Container1</Name>
<Parent>pnlScreenArea</Parent>
<Top>58</Top>
<Visible>True</Visible>
<Width>202</Width>
<tTFTButton>
<Caption>Skip</Caption>
<Color>clSilver</Color>
<Enabled>True</Enabled>
<Fixed>False</Fixed>
<FontColor>clWindowText</FontColor>
<FontRef>BigBold</FontRef>
<Height>32</Height>
<Left>20</Left>
<Name>btnSkip</Name>
<OnClick>btnSkip_OnClick</OnClick>
<Parent>Container1</Parent>
<Pen>78650656<Color>clBlack</Color><Width>1</Width></Pen>
<PressColor>clBlack</PressColor>
<Rounded>False</Rounded>
<Top>97</Top>
<Transparent>False</Transparent>
<Visible>True</Visible>
<Width>64</Width>
</tTFTButton>
<tTFTStaticLabel>
<Caption>to set up or Skip to continue</Caption>
<Enabled>True</Enabled>
<Fixed>False</Fixed>
<FontColor>clWindowText</FontColor>
<FontRef>Default</FontRef>
<Height>16</Height>
<Left>18</Left>
<Name>StaticLabel6</Name>
<Parent>Container1</Parent>
<Top>52</Top>
<Visible>True</Visible>
<Width>164</Width>
</tTFTStaticLabel>
<tTFTButton>
<Caption>OK</Caption>
<Color>clSilver</Color>
<Enabled>True</Enabled>
<Fixed>False</Fixed>
<FontColor>clWindowText</FontColor>
<FontRef>BigBold</FontRef>
<Height>32</Height>
<Left>124</Left>
<Name>btnOK</Name>
<OnClick>btnSkip_OnPress</OnClick>
<Parent>Container1</Parent>
<Pen>78650432<Color>clBlack</Color><Width>1</Width></Pen>
<PressColor>clBlack</PressColor>
<Rounded>True</Rounded>
<Top>95</Top>
<Transparent>False</Transparent>
<Visible>True</Visible>
<Width>64</Width>
</tTFTButton>
<tTFTStaticLabel>
<Caption>since installation. Choose OK</Caption>
<Enabled>True</Enabled>
<Fixed>False</Fixed>
<FontColor>clWindowText</FontColor>
<FontRef>Default</FontRef>
<Height>16</Height>
<Left>18</Left>
<Name>StaticLabel5</Name>
<Parent>Container1</Parent>
<Top>34</Top>
<Visible>True</Visible>
<Width>172</Width>
</tTFTStaticLabel>
<tTFTStaticLabel>
<Caption>Controller has not been setup</Caption>
<Enabled>True</Enabled>
<Fixed>False</Fixed>
<FontColor>clWindowText</FontColor>
<FontRef>Default</FontRef>
<Height>16</Height>
<Left>18</Left>
<Name>StaticLabel4</Name>
<Parent>Container1</Parent>
<Top>17</Top>
<Visible>True</Visible>
<Width>170</Width>
</tTFTStaticLabel>
</tTFTContainer>
</Screen>
Using IXMLIntf and XMLDoc I have written a recursive routine which works down the XMLNodes. It all works fine until the first Object under tTFTContainer. I iterate through the nodes starting at FirstSibling and looping using NextSibling until the Node returned is nil. When I get to the tTFTButton, the node returned by NextSibling is actually the first child node of the tTFTButton (Caption). I can't pick up on the element tTFTButton.
I am using IsTextElement to determine if the Node is carrying a property. I had assumed that IsTextElement returning false would stop at tTFTButton so I could use this Node to pass back into my routine.
This is the routine....
function XMLToObject(ObjNode: IXMLNode;
Scrn: tfmWorkingScreen;
ParentCtrl: TWinControl): Boolean;
// Creates and Registers a TControl based on the XML definition of the object passed
// if object is a container all objects in that container will also be handled.
// Returns true if Object created and registered.
function IsEvent(NodeName: String): Boolean;
begin
Result := (NodeName = 'OnClick')
Or (NodeName = 'OnUp')
Or (NodeName = 'OnPress')
Or (NodeName = 'OnDown');
end;
Procedure SetPropVal(PropName: String; PropVal: String); //OleVariant);
begin
ObjProps.FindProperty(PropName).AsString := PropVal;
end;
Var PropNode, SubNode: IXMLNode;
ObjIdx: Integer;
s: String;
begin
Result := Assigned(ObjNode);
if Assigned(ObjNode) then begin
ObjIdx := IndexOfObject(ObjNode.NodeName); // Index into Objects list
if (ObjIdx > -1) and (ObjIdx < ObjCount) then begin
PropNode := ObjNode.ChildNodes.FindNode('Name');
ObjProps.Instance := CreateObj(PropNode.NodeValue,ObjIdx, Scrn, ParentCtrl);
Scrn.RegisterAndAssign(TControl(ObjProps.Instance)); // register object to Screen
Result := Assigned(ObjProps.Instance); //
if not result then begin
PropNode := ObjNode.ChildNodes.First;
while Assigned(PropNode) do begin
if (PropNode.IsTextElement) then begin // if it is a property (Assumes Pen has propvalue)
// This should also be done recursively
if PropNode.ChildNodes.Count > 1 then begin // if it has child properties
SubNode := PropNode.ChildNodes.First;
while Assigned(SubNode) do begin
s := PropNode.NodeName + '.' + SubNode.NodeName;
ObjProps.FindProperty(s).AsString := subNode.NodeValue;
SubNode := SubNode.NextSibling;
end;
end
else
if IsEvent(PropNode.NodeName) then // Set up the events
Scrn.SetEventVal(ObjProps.Instance.Name, PropNode.NodeName, PropNode.Text);
ObjProps.FindProperty(PropNode.NodeName).AsString := PropNode.NodeValue; // Set property value
end
else
begin
SubNode := PropNode;
while Assigned(SubNode) do begin
ShowMessage(SubNode.NodeName + ' ' + IntToStr(PropNode.ParentNode.ChildNodes.Count) + ' ' + PropNode.Text); // Debug
Result := XMLToObject(SubNode, Scrn, TWinControl(ObjProps.Instance)); // recurse through container objects
if Result then
SubNode := SubNode.NextSibling
else
break;
end;
end;
if Not Result then Break; // Get out if error
PropNode := PropNode.NextSibling; // move on to next item
end;
end;
end;
end;
end;
and this is how it is called. PropNode is the first XML node which carries object information....
while Assigned(PropNode) do begin
if XMLToObject(PropNode, WorkScrn, WorkScrn.pnlScreenArea) then
PropNode := PropNode.NextSibling
else
begin
MessageDlg('Unable to process ' + PropNode.NodeName + ' in ' + fFileName,
mtWarning, [mbOK], 0);
break;
end;
end;
And here is the full XML file...
I hope that all makes sense. I am not sure if I am using XML correctly here, I was trying to make an XML version of a Text DMF file.