加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

如何从XPath选择中获取IXMLNodeList?

发布时间:2020-12-15 09:47:29 所属栏目:大数据 来源:网络整理
导读:我遇到了 a question about XPath and Delphi TXmlDocument. 虽然答案适用于选择单个xml节点,但我想用它来选择节点列表. 我找到了一个应该完全正确的similar utility function,但它无法正常工作. 显然有马车的功能: uses Xml.Xmldom,Xml.XMLIntf,Xml.XMLDoc
我遇到了 a question about XPath and Delphi TXmlDocument.

虽然答案适用于选择单个xml节点,但我想用它来选择节点列表.

我找到了一个应该完全正确的similar utility function,但它无法正常工作.

显然有马车的功能:

uses
  Xml.Xmldom,Xml.XMLIntf,Xml.XMLDoc;

function SelectNodes(xnRoot: IXmlNode; const nodePath: WideString): IXMLNodeList;
var
  intfSelect : IDomNodeSelect;
  intfAccess : IXmlNodeAccess;
  dnlResult  : IDomNodeList;
  intfDocAccess : IXmlDocumentAccess;
  doc: TXmlDocument;
  i : Integer;
  dn : IDomNode;
begin
  Result := nil;
  if not Assigned(xnRoot)
    or not Supports(xnRoot,IXmlNodeAccess,intfAccess)
    or not Supports(xnRoot.DOMNode,IDomNodeSelect,intfSelect) then
    Exit;

  dnlResult := intfSelect.selectNodes(nodePath);
  if Assigned(dnlResult) then
  begin
    Result := TXmlNodeList.Create(intfAccess.GetNodeObject,'',nil);
    if Supports(xnRoot.OwnerDocument,IXmlDocumentAccess,intfDocAccess) then
      doc := intfDocAccess.DocumentObject
    else
      doc := nil;

    for i := 0 to dnlResult.length - 1 do
    begin
      dn := dnlResult.item[i];
      Result.Add(TXmlNode.Create(dn,nil,doc));
    end;
  end;
end;

不使用IXMLNodeList的简化版本,而是使用“原始”IDomNodeList:

function SimpleSelectNodes(xnRoot: IXmlNode; const nodePath: WideString): IDOMNodeList;
var
  intfSelect : IDomNodeSelect;
begin
  Result := nil;
  if not Assigned(xnRoot)
    or not Supports(xnRoot.DOMNode,intfSelect) then
    Exit;

  Result := intfSelect.selectNodes(nodePath);
end;

测试代码:

procedure TForm1.FormCreate(Sender: TObject);
var
  Doc: IXMLDocument;
  Root: IXMLNode;
  DomNodeList: IDomNodeList;
  XmlNodeList: IXMLNodeList;
  XmlNode : IXMLNode;
  I: Integer;
begin
  // Build a test DOM tree in memory
  Doc := NewXMLDocument;
  Root := Doc.AddChild('root');
  Root.AddChild('C1');
  Root.AddChild('C2');
  Root.AddChild('C3');

  // Select using the IDomNodeList interface
  DomNodeList := SimpleSelectNodes(Root,'/root/*');
  for I := 0 to DomNodeList.length - 1 do
    ShowMessage(DomNodeList.item[I].nodeName);

  // Select using the IXMLNodeList interface
  XmlNodeList := SelectNodes(Root,'/root/*');
  XmlNode := XmlNodeList.First;
  while XmlNode <> nil do
  begin
    ShowMessage(XmlNode.NodeName);
    XmlNode := XmlNode.NextSibling;
  end;
end;

虽然SimpleSelectNodes版本工作正常,但SelectNodes函数没有.

它返回一个IXMLNodeList,但是当我尝试实际遍历此列表时,我只得到第一个项目,NextSibling为nil.

如何让IXMLNodeList工作?

解决方法

我有同样的问题(基本相同的代码).

我可以解决它的唯一方法是通过索引迭代节点,因为NextSibling每次都因某种原因返回nil.像这样的东西有效:

var
  i: Integer;
  Nodes: IXMLNodeList;
  Node: IXMLNode;
begin
  Nodes := SelectNodes(...);
  for i := 0 to NodeList.Count - 1 do
  begin
    Node := NodeList.Nodes[i];
    // Process node
  end;
end;

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读