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)中测试的演示控制台应用程序:

 // reference  https://theroadtodelphi.wordpress.com/2013/05/29/enabling-xpath-selectnode-selectnodes-methods-in-vcl-and-firemonkey-apps/

 {$APPTYPE CONSOLE}
uses
{$IFDEF MSWINDOWS}
System.Win.ComObj,
Winapi.ActiveX,
{$ENDIF}
System.SysUtils,
Xml.XMLIntf,
Xml.adomxmldom,
Xml.XMLDom,
Xml.XMLDoc; 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; procedure TestXPath;
var
XMLDoc: IXMLDocument;
Root, Book, Author, Publisher: IXMLNode;
LNodeList: IDOMNodeList;
LNode: IDOMNode;
i: Integer;
begin
XMLDoc := TXMLDocument.Create(nil);
XMLDoc.Active := True;
XMLDoc.Options := XMLDoc.Options + [doNodeAutoIndent];
XMLDoc.Version := '1.0'; Root := XMLDoc.CreateNode('BookStore');
Root.Attributes['url'] := 'http://www.amazon.com';
XMLDoc.documentElement := Root; Book := XMLDoc.CreateNode('Book');
Book.Attributes['Name'] := 'Steve Jobs';
Author := XMLDoc.CreateNode('Author');
Author.Text := 'Walter Isaacson';
Publisher := XMLDoc.CreateNode('Publisher');
Publisher.Text := 'Simon Schuster (October 24, 2011)';
Root.ChildNodes.Add(Book);
Book.ChildNodes.Add(Author);
Book.ChildNodes.Add(Publisher); Book := XMLDoc.CreateNode('Book');
Book.Attributes['Name'] := 'Clean Code: A Handbook of Agile Software Craftsmanship';
Author := XMLDoc.CreateNode('Author');
Author.Text := 'Robert C. Martin';
Publisher := XMLDoc.CreateNode('Publisher');
Publisher.Text := 'Prentice Hall; 1 edition (August 11, 2008)';
Root.ChildNodes.Add(Book);
Book.ChildNodes.Add(Author);
Book.ChildNodes.Add(Publisher); Book := XMLDoc.CreateNode('Book');
Book.Attributes['Name'] := 'Paradox Lost';
Author := XMLDoc.CreateNode('Author');
Author.Text := 'Kress, Peter';
Publisher := XMLDoc.CreateNode('Publisher');
Publisher.Text := 'Prentice Hall; 1 edition (February 2, 2000)';
Root.ChildNodes.Add(Book);
Book.ChildNodes.Add(Author);
Book.ChildNodes.Add(Publisher); Writeln(XMLDoc.Xml.Text); Writeln('selectSingleNode');
LNode := selectSingleNode(XMLDoc.DOMDocument, '/BookStore/Book[2]/Author["Robert C. Martin"]');
if LNode <> nil then
Writeln(LNode.firstChild.nodeValue); Writeln; Writeln('SelectNodes');
LNodeList := SelectNodes(XMLDoc.DOMDocument, '//BookStore/Book/Author');
if LNodeList <> nil then
for i := to LNodeList.length - do
Writeln(LNodeList[i].firstChild.nodeValue);
end; begin
try
ReportMemoryLeaksOnShutdown := True;
DefaultDOMVendor := OpenXML4Factory.Description;
{$IFDEF MSWINDOWS}CoInitialize(nil); {$ENDIF}
try
TestXPath;
finally
{$IFDEF MSWINDOWS}CoUninitialize; {$ENDIF}
end;
except
{$IFDEF MSWINDOWS}
on E: EOleException do
Writeln(Format('EOleException %s %x', [E.Message, E.ErrorCode]));
{$ENDIF}
on E: Exception do
Writeln(E.Classname, ':', E.Message);
end;
Writeln;
Writeln('Press Enter to exit');
Readln; end.

在Vcl和FireMonkey应用程序中启用TXMLDocument 的XPath(selectNode,selectNodes)方法的更多相关文章

  1. linux c程序中获取shell脚本输出的实现方法

    linux c程序中获取shell脚本输出的实现方法 1. 前言Unix界有一句名言:“一行shell脚本胜过万行C程序”,虽然这句话有些夸张,但不可否认的是,借助脚本确实能够极大的简化一些编程工作. ...

  2. VC++ 在两个程序中 传送字符串等常量值的方法:使用了 WM_COPYDATA 消息(转载)

    转载:http://www.cnblogs.com/renyuan/p/5037536.html VC++ 在两个程序中 传递字符串等常量值的方法:使用了 WM_COPYDATA 消息的 消息作用:  ...

  3. 在Windows程序中启用console输出-2016.01.04

    在某些时候,我们可能需要在Win32窗口应用程序中打开控制台窗口,打印一些消息,或者作为当前程序的另外一个人机交互界面,或者为了帮助调试程序.为了达到这种效果,需要了解函数AllocConsole和C ...

  4. ASP.NET MVC3 Web应用程序中启用GZip压缩示例

    http://www.mzwu.com/article.asp?id=3284 自定义一个筛选器,继承于GZipAttribute: using System;using System.IO.Comp ...

  5. VC++ 在两个程序中 传递字符串等常量值的方法:使用了 WM_COPYDATA 消息的

    消息作用:    在进程间共享数据(内部通过创建内存映射文件) 消息介绍:需要用到的数据结构/类型:typedef struct tagCOPYDATASTRUCT {    ULONG_PTR dw ...

  6. 关于微信小程序中的样式使用变量值的方法

    在开发过程中,通常碰到样式非固定的情况,这时候就要使用变量来规定样式,例如,一个view的宽度需要使用变量: 1. 在wxss中,定义变量:width:var(--width--); 2. 在js中, ...

  7. 在程序中通过Process启动外部exe的方法及注意事项

    启动外部进程的方法: /// <summary> /// 启动外部进程 /// </summary> /// <param name="path"&g ...

  8. 在ASP.NET应用程序中使用身份模拟(Impersonation)

    摘要   缺省情况下,ASP.NET应用程序以本机的ASPNET帐号运行,该帐号属于普通用户组,权限受到一定的限制,以保障ASP.NET应用程序运行的安全.但是有时需要某个ASP.NET应用程序或者程 ...

  9. 在 ASP.NET Core 中启用跨域请求(CORS)

    本文介绍如何在 ASP.NET Core 的应用程序中启用 CORS. 浏览器安全可以防止网页向其他域发送请求,而不是为网页提供服务. 此限制称为相同源策略. 同一源策略可防止恶意站点读取另一个站点中 ...

随机推荐

  1. Linux OOM一二三

    Linux开发一般会遇到“/proc/sys/vm/overcommit_memory”,即文件/etc/sysctl.conf中的vm.overcommit_memory,Overcommit的意思 ...

  2. 《Java虚拟机JVM故障诊断与性能优化》读书笔记(未完待续)

    前言: 对于JVM学习用处的理解:我们程序员写的代码,虽说是放在服务器(linux)系统上的.但是很多时候,受JVM的影响,其实程序并没有发挥出服务器的最大性能.这时候,JVM就成为了瓶颈了.有瓶颈就 ...

  3. Fiddler添加过滤条件

  4. SonarQube代码评审工具简介

    SonarQube是一个代码评审工具,可以完成对多种类型代码的扫描,并生成报告.本文是一个简单的扫描Java代码的使用说明. 该工具主要分为两个部分: 服务端:用来保存和展示扫描结果. 客户端:或者说 ...

  5. 如何单独编译Linux内核源码中的驱动为可加载模块?

    答: 分为两步: 1. 配置某个驱动为模块(如: CONFIG_RTC_XXX=m) 2. 指定路径并编译, 如编译drivers/rtc中的驱动 make SUBDIRS=drivers/rtc m ...

  6. Error-ASP.NET:未能加载文件或程序集“CMSCalendar”或它的某一个依赖项。系统找不到指定的文件。

    ylbtech-Error-ASP.NET:未能加载文件或程序集“CMSCalendar”或它的某一个依赖项.系统找不到指定的文件. 1.返回顶部 1. “/”应用程序中的服务器错误. 分析器错误 说 ...

  7. c++ 二进制方式读取文件 读取特殊类型数据

    #include <iostream> #include <fstream> using namespace std; /* 二进制方式进行读写文件,可以读写 各种各样数据类型 ...

  8. tomcat 启动和关闭脚本

    start.sh #!/bin/sh . ~/.bash_profile echo "" > ${TOMCAT_HOME}/logs/catalina.out; sh ${T ...

  9. mysql的几个操作

    1.忘记密码,从控制台免密码登录: 修改/etc/my.cnf,[mysqld]下加一行:skip-grant-tables 重启mysql: /etc/init.d/mysqld restart 命 ...

  10. elk使用记录

    1.使用elk查询接口的时候 几个常用参数  http_host.raw 2.具体的接口名称:request_uri 3.想要把左边要查询的显示出来