【问题标题】:Can I convert a msxml.IXMLDOMNode to XmlIntf.IXMLNode in Delphi?我可以在 Delphi 中将 msxml.IXMLDOMNode 转换为 XmlIntf.IXMLNode 吗?
【发布时间】:2011-12-30 05:49:51
【问题描述】:

我已将 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;

【问题讨论】:

    标签: xml delphi delphi-xe msxml


    【解决方案1】:

    您可以创建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.
    

    【讨论】:

    • msxmldom 单元似乎包含一些有用的类,谢谢。但我仍然希望能够只转换单个节点 - 而不是整个文档。否则,我将不得不从新文档对象中再次选择要处理的节点...
    • 我已经修改了这个例子来展示如何获得一个围绕现有IXMLDOMNodeIXMLNode 包装器。 TXMLNode 实现 IXMLNode 仍然需要所有者文档。
    • 该代码似乎创建了一个有效的 IXMLNode 实例。但是,当尝试访问节点的 Attributes 属性时,我将其传递给的实用程序函数会引发 [EIntfCastError] Interface not supported 异常...
    • 你有没有发现其他问题?谢谢!
    • 不...这似乎可以解决问题。谢谢!虽然它比解决方法要多得多的代码 - 但感觉更“正确”。
    猜你喜欢
    • 2011-12-21
    • 1970-01-01
    • 1970-01-01
    • 2020-06-30
    • 2010-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-02
    相关资源
    最近更新 更多