Delphi 找到 xml 节点

Delphi find xml node

我想在这里解决一个非常简单的问题:我想按名称找到一个节点并读取它的文本。

Function GetNodeText(xml,targetNode,value:string):String;
var
  xmldoc : IXMLDocument;
  root:    IXMLNode;
  i: LongInt;
  x:integer;
  s: string;
begin
  xmlDoc := newXMLDocument;
  xmlDoc.LoadFromXML(xml);
  xmlDoc.Active := true;

  root := XMLDoc.DocumentElement;

  for i := 0 to xmlDoc.ChildNodes[root.NodeName].ChildNodes.Count -1 do
  begin
    s := xmlDoc.DocumentElement.ChildNodes[i].NodeName;
    x := CompareStr(s, targetNode);
    if x = 0 then //targetnode Node found
    begin
      try
        result := xmlDoc.DocumentElement.ChildNodes[i].ChildNodes.FindNode(value).Text;
      Except
        result := '';
      end;
      exit;
    end
  end
end;

我的函数仅适用于 rootNode 的子节点。我如何浏览 XML 文档的所有现有节点直到到达结尾?

<?xml version="1.0"?>
<Customers>
    <customer>
        <id>1</id>          
        <Name>Ali</Name>
        <Age>34</Age>
        <favourite_car>
            <manufacturer>Porsche</manufacturer>
        </favourite_car>
    </customer>
    <customer>
        <Name>Hakan</Name>
        <id>2</id>          
        <Age>35</Age>
        <favourite_car>
            <manufacturer>BMW</manufacturer>
            <stack>overflow</stack>
        </favourite_car>
    </customer>
</Customers>

递归节点搜索是一个很好的提示。在另一个线程的帮助下,我能够构建一个解决方案:

function RecursiveFindNode(ANode: IXMLNode; const SearchNodeName: string): String;
var
  I: Integer;
begin
  if CompareText(ANode.NodeName, SearchNodeName) = 0 then
    begin
      if Assigned(ANode) then result := ANode.Text;
    end
  else if not Assigned(ANode.ChildNodes) then Result := ''
  else begin
    for I := 0 to ANode.ChildNodes.Count - 1 do
    begin
      Result := RecursiveFindNode(ANode.ChildNodes[I], SearchNodeName);
      if Result  <> '' then Exit;
    end;
  end;
end;

上述函数的版本略有改动。它没有返回文本,而是 returns IXMLNode.

function RecursiveFindNode(
  ANode: IXMLNode; const SearchNodeName: string): IXMLNode;
var
  I: Integer;
begin
  Result := nil;             
  if not Assigned(ANode) then
    exit;

  if CompareText(ANode.NodeName, SearchNodeName) = 0 then
    Result := ANode
  else
    if Assigned(ANode.ChildNodes) then
      for I := 0 to ANode.ChildNodes.Count - 1 do
      begin
        Result := RecursiveFindNode(ANode.ChildNodes[I], SearchNodeName);
        if Result <> nil then
          Exit;
      end;
end;