我发现了一篇关于XPath和Delphi TXmlDocument的问题(链接1)。
虽然该答案可以用于选择单个xml节点,但我想使用它来选择一个节点列表。
我找到了一个类似的实用函数,据说可以完美地实现这一功能,但它不能正常工作。
这个看起来有缺陷的函数:
虽然该答案可以用于选择单个xml节点,但我想使用它来选择一个节点列表。
我找到了一个类似的实用函数,据说可以完美地实现这一功能,但它不能正常工作。
这个看起来有缺陷的函数:
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, IDomNodeSelect, 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
正常工作?