我可以在Delphi中将msxml.IXMLDOMNode转换为XmlIntf.IXMLNode吗?

时间:2011-11-16 08:57:21

标签: xml delphi delphi-xe msxml

我已将som xml读入msxml.IXMLDOMDocument对象。但是,我正在使用的API中有一个实用方法,我想调用它,但它需要一个XmlIntf.IXMLNode作为参数。

有没有一种简单的方法可以将IXMLDOMNode实例从我的文档转换为IXMLNode,这样我就可以将它传递给方法而无需将xml加载到TXmlDocument对象中?

目前我已实施此解决方法:

function ConvertNode(const Node: IXMLDOMNode): IXMLNode;
var
  Document: IXMLDocument;
begin
  Document := NewXMLDocument;
  Document.LoadFromXML(Node.xml);
  Result := Document.DocumentElement;
end;

1 个答案:

答案 0 :(得分:11)

您可以创建IXMLDocument和"附加"的实例它到你的IXMLDOMDocument。这是一个小例子:

program msxmltest;

{$APPTYPE CONSOLE}

uses
  SysUtils, ActiveX,
  msxml, msxmldom,
  xmldom,
  XMLIntf, XMLDoc;

function MSDOMDocumentToDOMDocument(const MSDOMDocument: IXMLDOMDocument): IDOMDocument;
begin
  Result := TMSDOMDocument.Create(MSDOMDocument) as IDOMDocument;
end;

function MSDOMNodeToDOMNode(const MSDOMNode: IXMLDOMNode): IDOMNode;
const
  NodeClasses: array[ELEMENT_NODE..NOTATION_NODE] of TMSDOMNodeClass =
    (TMSDOMElement, TMSDOMAttr, TMSDOMText, TMSDOMCDataSection,
     TMSDOMEntityReference, TMSDOMEntity, TMSDOMProcessingInstruction,
     TMSDOMComment, TMSDOMDocument, TMSDOMDocumentType, TMSDOMDocumentFragment,
     TMSDOMNotation);
begin
  Result := NodeClasses[MSDOMNode.nodeType].Create(MSDOMNode) as IDOMNode;
end;

function MSDOMNodeToXMLNode(const MSDOMNode: IXMLDOMNode; var OwnerDocument: IXMLDocument): IXMLNode;
begin
  Result := nil;
  if not Assigned(MSDOMNode) then
    Exit;
  if not Assigned(OwnerDocument) then
  begin
    OwnerDocument := TXMLDocument.Create(nil);
    OwnerDocument.DOMDocument := MSDOMDocumentToDOMDocument(MSDOMNode.ownerDocument);
  end;
  Result := TXMLNode.Create(MSDOMNodeToDOMNode(MSDOMNode), nil, (OwnerDocument as IXMLDocumentAccess).DocumentObject);
end;

var
  Indent: Integer = 0;

procedure ShowNode(const Node: IXMLNode);
var
  I: Integer;
begin
  Inc(Indent);
  Writeln;
  Writeln(StringOfChar(' ', Indent * 2) + 'NodeName: ' + Node.NodeName);
  Writeln(StringOfChar(' ', Indent * 2) + 'NodeType: ' + NodeTypeNames[Node.NodeType]);
  for I := 0 to Node.AttributeNodes.Count - 1 do
    ShowNode(Node.AttributeNodes[I]);
  if Node.HasChildNodes then
    for I := 0 to Node.ChildNodes.Count - 1 do
      ShowNode(Node.ChildNodes[I])
  else
    Writeln(StringOfChar(' ', Indent * 2) + 'NodeValue: ' + Node.NodeValue);
  Dec(Indent);
end;

procedure Main;
var
  MSDOMDocument: IXMLDOMDocument;
  XMLDocument: IXMLDocument;
  MSDOMNode: IXMLDOMNode;
begin
  MSDOMDocument := CoDOMDocument.Create;
  MSDOMDocument.load('C:\Program Files\Embarcadero\RAD Studio\8.0\ObjRepos\en\Code_Templates\Delphi\blockcomment.xml');
  MSDOMNode := MSDOMDocument.documentElement;
  // show all
  ShowNode(MSDOMNodeToXMLNode(MSDOMNode, XMLDocument)); // you can reuse XMLDocument
  Writeln;
  // show author
  MSDOMNode := MSDOMDocument.selectSingleNode('/codetemplate/template/author');
  ShowNode(MSDOMNodeToXMLNode(MSDOMNode, XMLDocument));

  Readln;
end;


begin
  ReportMemoryLeaksOnShutdown := True;
  try
    CoInitialize(nil);
    try
      Main;
    finally
      CoUninitialize;
    end;
  except
    on E: Exception do
    begin
      ExitCode := 1;
      Writeln(Format('[%s] %s', [E.ClassName, E.Message]));
    end;
  end;
end.