【问题标题】:Delphi find xml nodeDelphi查找xml节点
【发布时间】:2015-03-06 15:14:28
【问题描述】:

我正在尝试解决一个非常简单的问题:我想按名称查找节点并读取其文本。

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>

【问题讨论】:

  • 不看 XML 结构就无法判断。
  • 如果目标节点可以出现在 XML 中任何级别的任何位置,那么您必须使用递归搜索或 XPath 查询来找到它。
  • 您好,我已经添加了 XML 结构。如您所见,它非常简单。我对制造商很感兴趣。但我的代码只查找姓名和年龄。
  • 您的 xml 结构看起来不合理。每个客户都应该在 节点中,而不是在 .. 节点中。区分将由 或新字段完成,例如。请举例说明(使用 xml 数据示例)您将作为 targetNodevalue 传递给 GetNodeText 的内容以及您希望返回的内容。您是否已经按照 Remy 的建议尝试了递归搜索?
  • 您好,我已经相应地更新了 xml 结构。在这个结构的基础上,我想搜索一个名为“stack”的节点并获取它的值。正如 Remy 已经说过的,这个节点可以出现在结构中的任何地方。这就是为什么我尝试搜索所有节点,直到找到具有所需名称的节点。嗯,我还没有尝试递归搜索,但我现在就试一试。

标签: xml delphi find


【解决方案1】:

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

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;

【讨论】:

  • 您将如何使用此功能找到 Hakans favourite_car 制造商?
  • 被否决,因为对 Assigned(ANode) 的检查放错了位置。为防止 AV 因 ANode 被传递 nil 而导致,您需要在使用 ANode 之前进行检查。
【解决方案2】:

上述函数的一些改动版本。它不返回 Text,而是返回 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;

【讨论】:

    猜你喜欢
    • 2023-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-17
    • 2014-07-25
    • 1970-01-01
    • 2013-11-26
    相关资源
    最近更新 更多