通过XML文档递归

时间:2015-01-12 19:57:57

标签: xml delphi delphi-2007

我似乎无法遍历以下XML文件。

<?xml version="1.0" encoding="utf-8"?>
    <Screen>
      <Title>MainMenuScrn</Title>
      <Start>True</Start>
      <BackColor>clBlue</BackColor>
      <Orientation>orLandscape</Orientation>
      <Image>&lt;none&gt;</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>

使用IXMLIntf和XMLDoc我编写了一个递归例程,它可以解决XMLNodes问题。一切正常,直到tTFTContainer下的第一个Object。我遍历从FirstSibling开始的节点并使用NextSibling进行循环,直到返回的Node为nil。当我到达tTFTButton时,NextSibling返回的节点实际上是tTFTButton(Caption)的第一个子节点。我无法接受元素tTFTButton。

我使用IsTextElement来确定Node是否携带属性。我假设IsTextElement返回false将停在tTFTButton,所以我可以使用这个Node传回我的例程。

这是常规....

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;

这就是它的调用方式。 PropNode是第一个携带对象信息的XML节点....

    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;

这是完整的XML文件......

我希望一切都有道理。我不确定我是否正确使用XML,我正在尝试制作文本DMF文件的XML版本。

0 个答案:

没有答案