zoukankan      html  css  js  c++  java
  • 在Vcl和FireMonkey应用程序中启用TXMLDocument 的XPath(selectNode,selectNodes)方法

    TXMLDocument的类让你来操作VCL和FireMonkey应用程序的XML文件,但这个类没有实现直接的方式来调用XPath的相关方法(selectNode的selectNodes),所以你必须编写一组辅助函数来调用这些方法。

    通常你可以写这样的东西

    function selectSingleNode(ADOMDocument: IDOMDocument; const nodePath: WideString): IDOMNode;
    var
      LDomNodeSelect : IDomNodeSelect;
    begin
      if not Assigned(ADOMDocument) or not Supports(ADOMDocument.documentElement, IDomNodeSelect, LDomNodeSelect) then
       Exit;
      //or just LDomNodeSelect:= (ADOMDocument.documentElement as IDOMNodeSelect);
      Result:=LDomNodeSelect.selectNode(nodePath);
    end;
    function SelectNodes(ADOMDocument: IDOMDocument; const nodePath: WideString): IDOMNodeList; var LDomNodeSelect : IDomNodeSelect; begin if not Assigned(ADOMDocument) or not Supports(ADOMDocument.documentElement, IDomNodeSelect, LDomNodeSelect) then Exit; //or just LDomNodeSelect:= (ADOMDocument.documentElement as IDOMNodeSelect); Result:=LDomNodeSelect.selectNodes(nodePath); end;

    并这样使用:

    var
      XmlDoc: IXMLDocument;
      LNode : IDOMNode;
      i : Integer;
    begin
      XmlDoc := TXMLDocument.Create(nil);
      XmlDoc.Active := True;
      XmlDoc.Options := XmlDoc.Options + [doNodeAutoIndent];
      XmlDoc.Version := '1.0';
      ...
      ...
      LNode:=selectSingleNode(XmlDoc.DOMDocument,XPathExpr);

    上面的代码在Windows下使用MSXML提供程序作为默认DOM供应商可以正常工作,但在必须在OSX和Windows中运行FireMonkey应用程序中,必须将默认DOM供应商设置为ADOM(OpenXML)。

    DefaultDOMVendor := OpenXML4Factory.Description;

    现在,如果您尝试在ADOM供应商下使用上述功能(selectSingleNode,SelectNodes),您将获得一个非常好的例外

    EOleException Catastrophic failure 8000FFFF

    这个问题的根目录是Tox4DOMNode.selectNodeTox4DOMNode.selectNodes这些方法的实现,请检查下一个代码。

    function Tox4DOMNode.selectNode(const nodePath: WideString): IDOMNode;
    var
      xpath: TXpathExpression;
      xdomText: TDomText;
    begin
      Result := nil;
      if not Assigned(WrapperDocument) or not Assigned(WrapperDocument.WrapperDOMImpl) then
        Exit;
     
      xpath := WrapperDocument.WrapperDOMImpl.FXpath; //here the xpath is set with a nil value because the FXpath was no initialized  
      xpath.ContextNode := NativeNode; //Here the App crash because xpath is nil

    FXpath字段在Tox4DOMImplementation.InitParserAgent方法中初始化,该方法永远不会调用您使用Tox4DOMImplementation.loadFromStreamTox4DOMImplementation.loadxml方法的方法。因此,要解决此问题,必须在调用selectNode和selectNodes方法之前调用Tox4DOMImplementation.InitParserAgent函数。

    function selectSingleNode(ADOMDocument: IDOMDocument; const nodePath: WideString): IDOMNode;
    var
      LDomNodeSelect : IDomNodeSelect;
    begin
      if not Assigned(ADOMDocument) or not Supports(ADOMDocument.documentElement, IDomNodeSelect, LDomNodeSelect) then
       Exit;
      //or just LDomNodeSelect:= (ADOMDocument.documentElement as IDOMNodeSelect);
      if (DefaultDOMVendor = OpenXML4Factory.Description) then
        Tox4DOMNode(LDomNodeSelect).WrapperDocument.WrapperDOMImpl.InitParserAgent;
      Result:=LDomNodeSelect.selectNode(nodePath);
    end;
    function SelectNodes(ADOMDocument: IDOMDocument; const nodePath: WideString): IDOMNodeList; var LDomNodeSelect : IDomNodeSelect; begin if not Assigned(ADOMDocument) or not Supports(ADOMDocument.documentElement, IDomNodeSelect, LDomNodeSelect) then Exit; //or just LDomNodeSelect:= (ADOMDocument.documentElement as IDOMNodeSelect); if (DefaultDOMVendor = OpenXML4Factory.Description) then Tox4DOMNode(LDomNodeSelect).WrapperDocument.WrapperDOMImpl.InitParserAgent; Result:=LDomNodeSelect.selectNodes(nodePath); end;

    现在通过这些更改,您将能够使用ADOM供应商评估VCL和FireMonkey应用程序中的XPath表达式。

    这是在Windows和OSX (Delphi 10.3.2 Rio)中测试的演示控制台应用程序:

      1 // reference  https://theroadtodelphi.wordpress.com/2013/05/29/enabling-xpath-selectnode-selectnodes-methods-in-vcl-and-firemonkey-apps/
      2 
      3 {$APPTYPE CONSOLE}
      4 uses
      5 {$IFDEF MSWINDOWS}
      6   System.Win.ComObj,
      7   Winapi.ActiveX,
      8 {$ENDIF}
      9   System.SysUtils,
     10   Xml.XMLIntf,
     11   Xml.adomxmldom,
     12   Xml.XMLDom,
     13   Xml.XMLDoc;
     14 
     15 function selectSingleNode(ADOMDocument: IDOMDocument; const nodePath: WideString): IDOMNode;
     16 var
     17   LDomNodeSelect: IDomNodeSelect;
     18 begin
     19   if not Assigned(ADOMDocument) or not Supports(ADOMDocument.documentElement, IDomNodeSelect, LDomNodeSelect) then
     20     Exit;
     21   // or just LDomNodeSelect:= (ADOMDocument.documentElement as IDOMNodeSelect);
     22   if (DefaultDOMVendor = OpenXML4Factory.Description) then
     23     Tox4DOMNode(LDomNodeSelect).WrapperDocument.WrapperDOMImpl.InitParserAgent;
     24   Result := LDomNodeSelect.selectNode(nodePath);
     25 end;
     26 
     27 function SelectNodes(ADOMDocument: IDOMDocument; const nodePath: WideString): IDOMNodeList;
     28 var
     29   LDomNodeSelect: IDomNodeSelect;
     30 begin
     31   if not Assigned(ADOMDocument) or not Supports(ADOMDocument.documentElement, IDomNodeSelect, LDomNodeSelect) then
     32     Exit;
     33   // or just LDomNodeSelect:= (ADOMDocument.documentElement as IDOMNodeSelect);
     34   if (DefaultDOMVendor = OpenXML4Factory.Description) then
     35     Tox4DOMNode(LDomNodeSelect).WrapperDocument.WrapperDOMImpl.InitParserAgent;
     36   Result := LDomNodeSelect.SelectNodes(nodePath);
     37 end;
     38 
     39 procedure TestXPath;
     40 var
     41   XMLDoc: IXMLDocument;
     42   Root, Book, Author, Publisher: IXMLNode;
     43   LNodeList: IDOMNodeList;
     44   LNode: IDOMNode;
     45   i: Integer;
     46 begin
     47   XMLDoc := TXMLDocument.Create(nil);
     48   XMLDoc.Active := True;
     49   XMLDoc.Options := XMLDoc.Options + [doNodeAutoIndent];
     50   XMLDoc.Version := '1.0';
     51 
     52   Root := XMLDoc.CreateNode('BookStore');
     53   Root.Attributes['url'] := 'http://www.amazon.com';
     54   XMLDoc.documentElement := Root;
     55 
     56   Book := XMLDoc.CreateNode('Book');
     57   Book.Attributes['Name'] := 'Steve Jobs';
     58   Author := XMLDoc.CreateNode('Author');
     59   Author.Text := 'Walter Isaacson';
     60   Publisher := XMLDoc.CreateNode('Publisher');
     61   Publisher.Text := 'Simon Schuster (October 24, 2011)';
     62   Root.ChildNodes.Add(Book);
     63   Book.ChildNodes.Add(Author);
     64   Book.ChildNodes.Add(Publisher);
     65 
     66   Book := XMLDoc.CreateNode('Book');
     67   Book.Attributes['Name'] := 'Clean Code: A Handbook of Agile Software Craftsmanship';
     68   Author := XMLDoc.CreateNode('Author');
     69   Author.Text := 'Robert C. Martin';
     70   Publisher := XMLDoc.CreateNode('Publisher');
     71   Publisher.Text := 'Prentice Hall; 1 edition (August 11, 2008)';
     72   Root.ChildNodes.Add(Book);
     73   Book.ChildNodes.Add(Author);
     74   Book.ChildNodes.Add(Publisher);
     75 
     76   Book := XMLDoc.CreateNode('Book');
     77   Book.Attributes['Name'] := 'Paradox Lost';
     78   Author := XMLDoc.CreateNode('Author');
     79   Author.Text := 'Kress, Peter';
     80   Publisher := XMLDoc.CreateNode('Publisher');
     81   Publisher.Text := 'Prentice Hall; 1 edition (February 2, 2000)';
     82   Root.ChildNodes.Add(Book);
     83   Book.ChildNodes.Add(Author);
     84   Book.ChildNodes.Add(Publisher);
     85 
     86   Writeln(XMLDoc.Xml.Text);
     87 
     88   Writeln('selectSingleNode');
     89   LNode := selectSingleNode(XMLDoc.DOMDocument, '/BookStore/Book[2]/Author["Robert C. Martin"]');
     90   if LNode <> nil then
     91     Writeln(LNode.firstChild.nodeValue);
     92 
     93   Writeln;
     94 
     95   Writeln('SelectNodes');
     96   LNodeList := SelectNodes(XMLDoc.DOMDocument, '//BookStore/Book/Author');
     97   if LNodeList <> nil then
     98     for i := 0 to LNodeList.length - 1 do
     99       Writeln(LNodeList[i].firstChild.nodeValue);
    100 end;
    101 
    102 begin
    103   try
    104     ReportMemoryLeaksOnShutdown := True;
    105     DefaultDOMVendor := OpenXML4Factory.Description;
    106 {$IFDEF MSWINDOWS}CoInitialize(nil); {$ENDIF}
    107     try
    108       TestXPath;
    109     finally
    110 {$IFDEF MSWINDOWS}CoUninitialize; {$ENDIF}
    111     end;
    112   except
    113 {$IFDEF MSWINDOWS}
    114     on E: EOleException do
    115       Writeln(Format('EOleException %s %x', [E.Message, E.ErrorCode]));
    116 {$ENDIF}
    117     on E: Exception do
    118       Writeln(E.Classname, ':', E.Message);
    119   end;
    120   Writeln;
    121   Writeln('Press Enter to exit');
    122   Readln;
    123 
    124 end.
  • 相关阅读:
    codevs 2010 求后序遍历
    code vs 1013 求先序排列
    codevs 3143 二叉树的序遍历
    codevs 3083 二叉树
    找树的根和孩子
    1501 二叉树最大宽度和高度
    1758:二叉树
    sql 如何把查询得到的结果如何放入一个新表中
    2011的n次方
    计算2的N次方
  • 原文地址:https://www.cnblogs.com/rtcmw/p/11095993.html
Copyright © 2011-2022 走看看