Martijn在对他的回答的评论中提到了Vendor属性。
实际上,该属性被称为DOMVendor。
下面是一些示例代码,展示了它的工作原理。
示例代码依赖于一些辅助类,你可以在bo.codeplex.com上找到。
请注意,DOMVendor无法告诉您所使用的MSXML版本,但您可以询问它是否支持XPath。
旧版的MSXML(例如在普通的Windows 2003 Server安装中仍然存在)不支持XPath
,但支持XSLPattern
。
它们可以执行您的查询,但有时会返回不同的结果,或者出错。
各种子版本的MSXML6中也存在一些微妙的错误。
您需要6.30、6.20.1103。、6.20.2003.0或更高版本。6.3仅适用于Windows 7 / Windows 2008 Server。在Windows XP和Windows 2003 Server上,使用6.20版本。
找出哪些版本实际可用花费了我相当长的时间:-)
这显示了我安装的MSXML,在我的情况下是msxml6.dll:6.20.1103.0
:
procedure TMainForm.ShowMsxml6VersionClick(Sender: TObject);
begin
try
Logger.Log(TmsxmlFactory.msxmlBestFileVersion.ToString());
TmsxmlFactory.AssertCompatibleMsxml6Version();
except
on E: Exception do
begin
Logger.Log('Error');
Logger.Log(E);
end;
end;
end;
这里展示了DOMVendor
代码,它使用了一些辅助类,你可以在此找到。
procedure TMainForm.FillDomVendorComboBox;
var
DomVendorComboBoxItemsCount: Integer;
Index: Integer;
CurrentDomVendor: TDOMVendor;
DefaultDomVendorIndex: Integer;
CurrentDomVendorDescription: string;
const
NoSelection = -1;
begin
DomVendorComboBox.Clear;
DefaultDomVendorIndex := NoSelection;
for Index := 0 to DOMVendors.Count - 1 do
begin
CurrentDomVendor := DOMVendors.Vendors[Index];
LogDomVendor(CurrentDomVendor);
CurrentDomVendorDescription := CurrentDomVendor.Description;
DomVendorComboBox.Items.Add(CurrentDomVendorDescription);
if DefaultDOMVendor = CurrentDomVendorDescription then
DefaultDomVendorIndex := DomVendorComboBox.Items.Count - 1;
end;
DomVendorComboBoxItemsCount := DomVendorComboBox.Items.Count;
if (DefaultDomVendorIndex = NoSelection) then
begin
if DefaultDOMVendor = NullAsStringValue then
begin
if DomVendorComboBoxItemsCount > 0 then
DefaultDomVendorIndex := 0;
end
else
DefaultDomVendorIndex := DomVendorComboBoxItemsCount - 1;
end;
DomVendorComboBox.ItemIndex := DefaultDomVendorIndex;
end;
procedure TMainForm.LogDomVendor(const CurrentDomVendor: TDOMVendor);
var
CurrentDomVendorDescription: string;
DocumentElement: IDOMElement;
DomDocument: IDOMDocument;
XmlDocument: IXMLDocument;
XmlDocumentInstance: TXMLDocument;
DOMNodeEx: IDOMNodeEx;
XMLDOMDocument2: IXMLDOMDocument2;
begin
CurrentDomVendorDescription := CurrentDomVendor.Description;
Logger.Log('DOMVendor', CurrentDomVendorDescription);
XmlDocumentInstance := TXMLDocument.Create(nil);
XmlDocumentInstance.DOMVendor := CurrentDomVendor;
XmlDocument := XmlDocumentInstance;
DomDocument := CurrentDomVendor.DOMImplementation.createDocument(NullAsStringValue, NullAsStringValue, nil);
XmlDocument.DOMDocument := DomDocument;
XmlDocument.LoadFromXML('<document/>');
DomDocument := XmlDocument.DOMDocument;
DocumentElement := DomDocument.DocumentElement;
if Assigned(DocumentElement) then
begin
DOMNodeEx := DocumentElement as IDOMNodeEx;
Logger.Log(DOMNodeEx.xml);
end;
if IDomNodeHelper.GetXmlDomDocument2(DomDocument, XMLDOMDocument2) then
begin
Logger.Log(IDomNodeHelper.SelectionLanguage, string(XMLDOMDocument2.getProperty(IDomNodeHelper.SelectionLanguage)));
Logger.Log(IDomNodeHelper.SelectionNamespaces, string(XMLDOMDocument2.getProperty(IDomNodeHelper.SelectionNamespaces)));
end;
LogDomVendorFeatures(CurrentDomVendor,
['','1.0','2.0', '3.0'],
['Core'
,'XML'
,'Events'
,'UIEvents'
,'MouseEvents'
,'TextEvents'
,'KeyboardEvents'
,'MutationEvents'
,'MutationNameEvents'
,'HTMLEvents'
,'LS'
,'LS-Async'
,'Validation'
,'XPath'
]);
end;
procedure TMainForm.LogDomVendorFeatures(const CurrentDomVendor: TDOMVendor; const Versions, Features: array of string);
var
AllVersions: string;
Feature: string;
Line: string;
Supported: Boolean;
SupportedAll: Boolean;
SupportedNone: Boolean;
SupportedVersions: IStringListWrapper;
Version: string;
begin
SupportedVersions := TStringListWrapper.Create();
for Version in Versions do
AddSupportedVersion(Version, SupportedVersions);
AllVersions := Format('All: %s', [SupportedVersions.CommaText]);
for Feature in Features do
begin
SupportedAll := True;
SupportedNone := True;
SupportedVersions.Clear();
for Version in Versions do
begin
Supported := CurrentDomVendor.DOMImplementation.hasFeature(Feature, Version);
if Supported then
AddSupportedVersion(Version, SupportedVersions);
SupportedAll := SupportedAll and Supported;
SupportedNone := SupportedNone and not Supported;
end;
if SupportedNone then
Line := Format('None', [])
else
if SupportedAll then
Line := Format('%s', [AllVersions])
else
Line := Format('%s', [SupportedVersions.CommaText]);
Logger.Log(' ' + Feature, Line);
end;
end;
Delphi XE 会显示这些内容:
DOMVendor:MSXML
<document/>
SelectionLanguage:XPath
SelectionNamespaces:
Core:None
XML:Any,1.0
Events:None
UIEvents:None
MouseEvents:None
TextEvents:None
KeyboardEvents:None
MutationEvents:None
MutationNameEvents:None
HTMLEvents:None
LS:None
LS-Async:None
Validation:None
XPath:Any,1.0
DOMVendor:ADOM XML v4
?<document></document>
Core:None
XML:None
Events:None
UIEvents:None
MouseEvents:None
TextEvents:None
KeyboardEvents:None
MutationEvents:None
MutationNameEvents:None
HTMLEvents:None
LS:None
LS-Async:None
Validation:None
XPath:None
xmlns="http://schemas.microsoft.com/search/local/ws/rest/v1"
,然后这个就可以正常工作了://Link[@role="self"][1]/node()
。我不知道你的示例中为什么有[3]
,因为文档中只有一个Link
节点;我不喜欢删除默认命名空间声明的解决方案,感觉很不专业... - Cosmin Prund