我正在尝试将一些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
因此Nodes
TNativeXML
属性似乎与IXMLNode
的{{1}}属性不完全相同。
如何迭代父节点中的所有子节点?我不想给每个人一个唯一的名字(ChildNodes
等),因为我只需要按顺序访问它们,并且不希望速度惩罚(或增加的文件大小)必须做每个值<v1001>1234</v1001>, <v1002>4321</v1002>...
(可能有很多这些值)。
更新**
NativeXML确实等同于NodeByName
- 它被称为ChildNodes
(不是Containers
,因为在线文档会让您相信)。以下工作:
ChildContainers
它实际上非常慢 - 读取32k浮点值需要10秒钟。
答案 0 :(得分:2)
OP:
所以似乎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