2

我正在尝试将一些 xml 代码从默认的 delphi XML 例程迁移到 NativeXML,希望能提高速度(很多)。

XML 文件的格式为:

<Datafile>
  <Header>
    <Name>'My Name'</Name>
    <Address>'My Address'</Address>
  </Header>
  <Body>
    <ValuesSets>
      <ValuesSet>
        <v>1</v>
        <v>2</v>
        <v>3</v>
        <v>4</v>
      </ValuesSet>
      <ValuesSet>
        <v>5</v>
        <v>6</v>
        <v>7</v>
        <v>8</v>
      </ValuesSet>
    </ValuesSets>
  </Body>
</Datafile>

我的问题是如何遍历每组值。旧代码的或多或少的直接翻译不起作用:

procedure TForm1.Button1Click(Sender: TObject);

var
    AXMLDoc       : TNativeXML ;
    FileID        : TFilename ;
    I             : Integer ;
    J             : Integer ;
    HeaderNode    : TXMLNode ;
    BodyNode      : TXMLNode ;
    ValuesSetsNode : TXMLNode ;
    ValuesSetNode  : TXMLNode ;

    Values         : array of array of integer ;

begin
try
    Memo1.Lines.Clear ;
    FileID := 'Sample.XML' ;
    Memo1.Lines.LoadFromFile (FileID) ;
    AXMLDoc := TNativeXml.Create (nil) ;
    AXMLDoc.LoadFromFile (FileID) ;

    if Assigned(AXMLDoc.Root) then
        begin
        HeaderNode := AXMLDoc.Root.NodeByName ('Header') ;
        if Assigned (HeaderNode) then
            begin
            //  < process header items >
            BodyNode := AXMLDoc .Root.NodeByName ('Body') ;
            if Assigned (BodyNode) then
                begin
                ValuesSetsNode := BodyNode.NodeByName ('ValuesSets') ;
                if Assigned (ValuesSetsNode) then
                    begin
                    SetLength (Values, ValuesSetsNode.NodeCount) ;
                    for i := 0 to ValuesSetsNode.NodeCount - 1 do
                        begin
                        ValuesSetNode := ValuesSetsNode [i] ;
                        if Assigned (ValuesSetNode) then
                            begin
                            SetLength (Values [i], ValuesSetNode.NodeCount) ;
                            for j := 0 to ValuesSetNode.NodeCount - 1 do
                                begin
                                Values [i, j] := StrToIntDef (ValuesSetNode [j].Value, 0) ;
                                end ;
                            end ;
                       end ;
                    end ;
                end ;
            end ;
        end ;

    for i := 0 to Length (Values) - 1 do
        begin
        for j := 0 to Length (Values [i]) - 1 do
            begin
            Memo1.Lines.Add (Format ('Values [%d, %d] = %d', [i, j, Values [i, j]])) ;
            end ;
       end ;

finally
    FreeAndNil (AXMLDoc) ;
    end ;
end ;

我得到的输出是:

Values [1, 0] = 0
Values [1, 1] = 1
Values [1, 2] = 0
Values [1, 3] = 2
Values [1, 4] = 0
Values [1, 5] = 3
Values [1, 6] = 0
Values [1, 7] = 4
Values [1, 8] = 0
Values [3, 0] = 0
Values [3, 1] = 5
Values [3, 2] = 0
Values [3, 3] = 6
Values [3, 4] = 0
Values [3, 5] = 7
Values [3, 6] = 0
Values [3, 7] = 8
Values [3, 8] = 0

我期待:

Values [0, 0] = 1
Values [0, 1] = 2
Values [0, 2] = 3
Values [0, 3] = 4
Values [1, 0] = 5
Values [1, 1] = 6
Values [1, 2] = 7
Values [1, 3] = 8

所以看起来好像 of 的Nodes属性与' 的属性TNativeXML并不完全相同。IXMLNodeChildNodes

如何迭代父节点中的所有子节点?我不想给每个人一个唯一的名称(<v1001>1234</v1001>, <v1002>4321</v1002>...等),因为我只需要按顺序访问它们,并且不希望必须NodeByName为每个值执行一个速度损失(或增加文件大小)(那里可以是许多这些值)。

更新 **

NativeXML 确实有一个等价物ChildNodes- 它被称为Containers(不像ChildContainers在线文档让你相信的那样)。以下工作:

var
    AXMLDoc       : TNativeXML ;
    FileID        : TFilename ;
    I             : Integer ;
    J             : Integer ;
    HeaderNode    : TXMLNode ;
    BodyNode      : TXMLNode ;
    ValuesSetsNode : TXMLNode ;
    ValuesSetNode  : TXMLNode ;

    Values         : array of array of integer ;

begin
try
    Memo1.Lines.Clear ;
    FileID := 'Sample.XML' ;
    Memo1.Lines.LoadFromFile (FileID) ;
    AXMLDoc := TNativeXml.Create (nil) ;
    AXMLDoc.LoadFromFile (FileID) ;

    if Assigned(AXMLDoc.Root) then
        begin
        HeaderNode := AXMLDoc.Root.NodeByName ('Header') ;
        if Assigned (HeaderNode) then
            begin
            //  < process header items >
            BodyNode := AXMLDoc .Root.NodeByName ('Body') ;
            if Assigned (BodyNode) then
                begin
                ValuesSetsNode := BodyNode.NodeByName ('ValuesSets') ;
                if Assigned (ValuesSetsNode) then
                    begin
                    SetLength (Values, ValuesSetsNode.ContainerCount) ;
                    for i := 0 to ValuesSetsNode.ContainerCount - 1 do
                        begin
                        ValuesSetNode := ValuesSetsNode.Containers [i] ;
                        if Assigned (ValuesSetNode) then
                            begin
                            SetLength (Values [i], ValuesSetNode.ContainerCount) ;
                            for j := 0 to ValuesSetNode.ContainerCount - 1 do
                                begin
                                Values [i, j] := StrToIntDef (ValuesSetNode.Containers [j].Value, 0) ;
                                end ;
                            end ;
                       end ;
                    end ;
                end ;
            end ;
        end ;

    for i := 0 to Length (Values) - 1 do
        begin
        for j := 0 to Length (Values [i]) - 1 do
            begin
            Memo1.Lines.Add (Format ('Values [%d, %d] = %d', [i, j, Values [i, j]])) ;
            end ;
       end ;

finally
    FreeAndNil (AXMLDoc) ;
    end ;
end ;

它实际上很慢 - 读取 32k 浮点值需要很多 10 秒。

4

1 回答 1

2

操作:

所以看起来 TNativeXML 的 Nodes 属性与 IXMLNode 的 ChildNodes 属性并不完全相同。

你说的对 。为了达到这个结果,必须做更多的事情。

在此处输入图像描述

procedure TForm1.Button1Click(Sender: TObject);
var
[...]
    i , i2        : Integer ;
    j , j2        : Integer ;
[...]
begin
try
    Memo1.Lines.Clear ;
    [...]
            BodyNode := AXMLDoc .Root.NodeByName ('Body') ;
             if Assigned (BodyNode) then
             begin
                 ValuesSetsNode := BodyNode.NodeByName ('ValuesSets') ;
                 if Assigned (ValuesSetsNode) then
                 begin
                     SetLength (Values, ValuesSetsNode.NodeCount) ;
                     ValuesSetNode := ValuesSetsNode.NodeByName('ValuesSet') ;
                     if Assigned (ValuesSetNode) then
                     begin
                       i2:=0;
                        for i := 0 to ValuesSetSNode.NodeCount - 1 do begin
                         if i > 0 then ValuesSetNode := ValuesSetsNode.NextSibling(ValuesSetNode) ;
                         if ValuesSetNode=nil then break;
                         if ValuesSetNode.NodeCount > 0 then begin
                            SetLength(Values[i2], ValuesSetNode.NodeCount) ;
                            j2:=0;
                               for j := 0 to ValuesSetNode.NodeCount - 1 do begin
                                if pos(#13,ValuesSetNode[j].Value) > 0 then continue;
                                Values [i2, j2] := StrToIntDef (ValuesSetNode[j].Value, 0) ;
                                inc(j2);
                               end ; // for j
                           SetLength(Values[i2],j2);
                           inc(i2);
                         end;
                        end ; // for i
                     end;     // ValuesSetNode
                 end;         // ValuesSetsNode
             end;             // BodyNode
        end;                  // HeaderNode
    end;                      // AXMLDoc.Root

[...] 

finally
    FreeAndNil (AXMLDoc) ;
    end ;
end ;

Delphi 5 / Delphi XE2 NativeXml 4.07

于 2013-05-28T01:39:28.740 回答