Switching Delphi XML DOM vendors
Posted by jpluimers on 2019/06/18
I thought I had written a blog article on switching DOM vendors before, but in retrospect that was a conference presentation somewhere in 2011: https://github.com/jpluimers/Conferences/tree/master/2011/EKON15-Renaissance-Hotel-D%C3%BCsseldorf/Delphi-XE2-and-XML
I mentioned some of the materials at [WayBack] delphi – Reading distinct values from XML using XPath – Stack Overflow.
It was back in the days I worked for better office, Gwan Tan was still alive and CodePlex was still a thing. Now the code is at [WayBack] bo library – CodePlex Archive: An archive of the CodePlex open source hosting site.
Some recovered bits are at https://gist.github.com/jpluimers/98dcec944538fd6986fd2d51f7a79d8b#file-mainformunit-pas that shows the selection process of a TDOMVendor, how to log its capabilities and how to use it all in the method procedure TMainForm.LogDomVendor(const CurrentDomVendor: TDOMVendor);
Hopefully one day I can resurrect the code one day…
Over the years, the vendor list has not changed much [WayBack] Using the Document Object Model – RAD Studio documents these vendors.
Compared to Delphi 2007 and earlier, OmniXML has gone and ADOM has entered.
On the MSXML side, you can change which version you use too, as explained in Quick tip: using MSXML v6 with TXMLDocument in D7-D2007 – DelphiFeeds.com with the original article at [WayBack] Quick tip: using MSXML v6 with TXMLDocument in D7-D2007 | Delphi Haven.
Basically he overwrites MSXMLDOMDocumentCreate with a method creating the right MSXML DOM document. That has now been deprecated as [WayBack] Xml.Win.msxmldom.MSXMLDOMDocumentCreate – RAD Studio API Documentation now points to [WayBack] Xml.Win.msxmldom.TMSXMLDOMDocumentFactory.CreateDOMDocument – RAD Studio API Documentation.
List of Built-in XML Vendors
The following table shows a comparison of the XML vendors that RAD Studio supports by default:
Implementation Unit Global Variable Description MSXML Xml.Win.msxmldom SMSXMLFastest of the built-in RAD Studio XML vendors. Windows only. Default. For cross-platform support, you must choose a different XML vendor. If you do not specify a different XML vendor, your application does not have XML support on other platforms than Windows, and you see a run-time exception when you run your application in other platforms.
OmniXML Xml.omnixmldomsOmniXmlVendorMuch faster than ADOM, but slightly slower than MSXML. Cross-platform. ADOM Xml.adomxmldomsAdom4XmlVendorSlower than the other built-in RAD Studio XML vendors. Cross-platform.
–jeroen
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| object MainForm: TMainForm | |
| Left = 0 | |
| Top = 0 | |
| Caption = 'XPathTester MainForm' | |
| ClientHeight = 573 | |
| ClientWidth = 792 | |
| Color = clBtnFace | |
| Font.Charset = DEFAULT_CHARSET | |
| Font.Color = clWindowText | |
| Font.Height = -11 | |
| Font.Name = 'Tahoma' | |
| Font.Style = [] | |
| OldCreateOrder = False | |
| OnCreate = FormCreate | |
| PixelsPerInch = 96 | |
| TextHeight = 13 | |
| object Splitter1: TSplitter | |
| Left = 394 | |
| Top = 159 | |
| Height = 414 | |
| ExplicitLeft = 328 | |
| ExplicitTop = 136 | |
| ExplicitHeight = 100 | |
| end | |
| object ActionPanel: TPanel | |
| Left = 0 | |
| Top = 0 | |
| Width = 792 | |
| Height = 159 | |
| Align = alTop | |
| TabOrder = 0 | |
| DesignSize = ( | |
| 792 | |
| 159) | |
| object Label1: TLabel | |
| Tag = 2 | |
| Left = 8 | |
| Top = 133 | |
| Width = 38 | |
| Height = 13 | |
| Caption = '&Vendor:' | |
| FocusControl = DomVendorComboBox | |
| end | |
| object XPathLabeledEdit: TLabeledEdit | |
| Left = 50 | |
| Top = 7 | |
| Width = 736 | |
| Height = 21 | |
| Anchors = [akLeft, akTop, akRight] | |
| EditLabel.Width = 32 | |
| EditLabel.Height = 13 | |
| EditLabel.Caption = 'X&Path:' | |
| LabelPosition = lpLeft | |
| TabOrder = 0 | |
| Text = '//bk:Book[position()<=2]' | |
| end | |
| object RunXPathButton: TButton | |
| Left = 50 | |
| Top = 34 | |
| Width = 135 | |
| Height = 25 | |
| Caption = '&Run XPath' | |
| TabOrder = 1 | |
| OnClick = RunXPathButtonClick | |
| end | |
| object LoadXmlButton: TButton | |
| Left = 191 | |
| Top = 34 | |
| Width = 135 | |
| Height = 25 | |
| Caption = '&Load XML file' | |
| TabOrder = 5 | |
| OnClick = LoadXmlButtonClick | |
| end | |
| object ShowNameSpacesButton: TButton | |
| Left = 50 | |
| Top = 65 | |
| Width = 135 | |
| Height = 25 | |
| Caption = 'Show &namespaces' | |
| TabOrder = 2 | |
| OnClick = ShowNameSpacesButtonClick | |
| end | |
| object LoadXmlExample1Button: TButton | |
| Left = 191 | |
| Top = 65 | |
| Width = 135 | |
| Height = 25 | |
| Caption = 'Load Example &1' | |
| TabOrder = 6 | |
| OnClick = LoadXmlExample1ButtonClick | |
| end | |
| object LoadXmlExample2Button: TButton | |
| Left = 191 | |
| Top = 96 | |
| Width = 135 | |
| Height = 25 | |
| Caption = 'Load Example &2' | |
| TabOrder = 7 | |
| OnClick = LoadXmlExample2ButtonClick | |
| end | |
| object HistoryGroupBox: TGroupBox | |
| Left = 332 | |
| Top = 34 | |
| Width = 453 | |
| Height = 119 | |
| Anchors = [akLeft, akTop, akRight, akBottom] | |
| Caption = '&History' | |
| TabOrder = 8 | |
| DesignSize = ( | |
| 453 | |
| 119) | |
| object HistoryListBox: TListBox | |
| Left = 8 | |
| Top = 16 | |
| Width = 435 | |
| Height = 94 | |
| Anchors = [akLeft, akTop, akRight, akBottom] | |
| ItemHeight = 13 | |
| TabOrder = 0 | |
| OnClick = HistoryListBoxClick | |
| end | |
| end | |
| object ShowMsxml6Version: TButton | |
| Left = 50 | |
| Top = 96 | |
| Width = 135 | |
| Height = 25 | |
| Caption = 'Show MSXML&6 version' | |
| TabOrder = 4 | |
| OnClick = ShowMsxml6VersionClick | |
| end | |
| object DomVendorComboBox: TComboBox | |
| Left = 50 | |
| Top = 129 | |
| Width = 135 | |
| Height = 21 | |
| ItemHeight = 0 | |
| TabOrder = 3 | |
| Text = 'DomVendorComboBox' | |
| end | |
| object LoadXmlExample3Button: TButton | |
| Left = 191 | |
| Top = 127 | |
| Width = 135 | |
| Height = 25 | |
| Caption = 'Load Example &3' | |
| TabOrder = 9 | |
| OnClick = LoadXmlExample3ButtonClick | |
| end | |
| end | |
| object ResultsGroupBox: TGroupBox | |
| Left = 397 | |
| Top = 159 | |
| Width = 395 | |
| Height = 414 | |
| Align = alClient | |
| Caption = '&Results' | |
| TabOrder = 1 | |
| object ResultsMemo: TMemo | |
| Left = 2 | |
| Top = 35 | |
| Width = 391 | |
| Height = 377 | |
| Align = alClient | |
| ScrollBars = ssBoth | |
| TabOrder = 0 | |
| WordWrap = False | |
| end | |
| object Panel1: TPanel | |
| Left = 2 | |
| Top = 15 | |
| Width = 391 | |
| Height = 20 | |
| Align = alTop | |
| BevelOuter = bvNone | |
| TabOrder = 1 | |
| object ShowTextInResultCheckBox: TCheckBox | |
| Left = 6 | |
| Top = 0 | |
| Width = 125 | |
| Height = 17 | |
| Caption = 'Show &text in results' | |
| TabOrder = 0 | |
| end | |
| object ShowXmlInResultCheckBox: TCheckBox | |
| Left = 205 | |
| Top = 0 | |
| Width = 131 | |
| Height = 17 | |
| Caption = '&Show XML in the results' | |
| TabOrder = 1 | |
| end | |
| end | |
| end | |
| object XmlGroupBox: TGroupBox | |
| Left = 0 | |
| Top = 159 | |
| Width = 394 | |
| Height = 414 | |
| Align = alLeft | |
| Caption = 'Xml' | |
| TabOrder = 2 | |
| object XmlPageControl: TPageControl | |
| Left = 2 | |
| Top = 15 | |
| Width = 390 | |
| Height = 397 | |
| ActivePage = XmlMemoTabSheet | |
| Align = alClient | |
| TabOrder = 0 | |
| OnChange = XmlPageControlChange | |
| object XmlMemoTabSheet: TTabSheet | |
| Caption = '&Edit' | |
| ExplicitLeft = 0 | |
| ExplicitTop = 0 | |
| ExplicitWidth = 0 | |
| ExplicitHeight = 0 | |
| object XmlMemo: TMemo | |
| Left = 0 | |
| Top = 0 | |
| Width = 382 | |
| Height = 369 | |
| Align = alClient | |
| Lines.Strings = ( | |
| '<?xml version="1.0"?>' | |
| '<bk:Books xmlns:bk='#39'http://myserver/myschemas/Books'#39'>' | |
| ' <bk:Book>' | |
| ' <bk:Title>Just XML</bk:Title>' | |
| ' </bk:Book>' | |
| ' <bk:Book>' | |
| ' <bk:Title>Professional XML</bk:Title>' | |
| ' </bk:Book>' | |
| ' <bk:Book>' | |
| ' <bk:Title>XML Step by Step</bk:Title>' | |
| ' </bk:Book>' | |
| ' <bk:Book>' | |
| ' <bk:Title>XML By Example</bk:Title>' | |
| ' </bk:Book>' | |
| '</bk:Books>') | |
| ScrollBars = ssBoth | |
| TabOrder = 0 | |
| WordWrap = False | |
| end | |
| end | |
| object XmlViewTabSheet: TTabSheet | |
| Caption = '&View' | |
| ImageIndex = 1 | |
| ExplicitLeft = 0 | |
| ExplicitTop = 0 | |
| ExplicitWidth = 0 | |
| ExplicitHeight = 0 | |
| object XmlWebBrowser: TWebBrowser | |
| Left = 0 | |
| Top = 0 | |
| Width = 382 | |
| Height = 369 | |
| Align = alClient | |
| TabOrder = 0 | |
| ExplicitLeft = 112 | |
| ExplicitTop = 120 | |
| ExplicitWidth = 300 | |
| ExplicitHeight = 150 | |
| ControlData = { | |
| 4C0000007B270000232600000000000000000000000000000000000000000000 | |
| 000000004C000000000000000000000001000000E0D057007335CF11AE690800 | |
| 2B2E126208000000000000004C0000000114020000000000C000000000000046 | |
| 8000000000000000000000000000000000000000000000000000000000000000 | |
| 00000000000000000100000000000000000000000000000000000000} | |
| end | |
| end | |
| object HistoryTabSheet: TTabSheet | |
| Caption = 'H&istory' | |
| ImageIndex = 2 | |
| ExplicitLeft = 0 | |
| ExplicitTop = 0 | |
| ExplicitWidth = 0 | |
| ExplicitHeight = 0 | |
| object HistoryMemo: TMemo | |
| Left = 0 | |
| Top = 0 | |
| Width = 382 | |
| Height = 369 | |
| Align = alClient | |
| TabOrder = 0 | |
| end | |
| end | |
| end | |
| end | |
| object XmlOpenDialog: TOpenDialog | |
| Filter = 'Xml files (*.xml)|*.xml|All files (*.*)|*.*' | |
| Options = [ofEnableSizing] | |
| Left = 370 | |
| Top = 68 | |
| end | |
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| unit MainFormUnit; | |
| interface | |
| uses | |
| Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, | |
| Dialogs, ExtCtrls, StdCtrls, ComCtrls, OleCtrls, SHDocVw, | |
| LoggerUnit, StringListWrapperUnit, LoggerInterfaceUnit, xmldom; | |
| // example XML from | |
| // 1. http://support.microsoft.com/kb/280457 | |
| // 2. http://msdn.microsoft.com/en-us/library/ms756048(VS.85).aspx | |
| type | |
| TMainForm = class(TForm) | |
| ActionPanel: TPanel; | |
| DomVendorComboBox: TComboBox; | |
| HistoryGroupBox: TGroupBox; | |
| HistoryListBox: TListBox; | |
| HistoryMemo: TMemo; | |
| HistoryTabSheet: TTabSheet; | |
| Label1: TLabel; | |
| LoadXmlButton: TButton; | |
| LoadXmlExample1Button: TButton; | |
| LoadXmlExample2Button: TButton; | |
| ResultsGroupBox: TGroupBox; | |
| ResultsMemo: TMemo; | |
| RunXPathButton: TButton; | |
| ShowMsxml6Version: TButton; | |
| ShowNameSpacesButton: TButton; | |
| Splitter1: TSplitter; | |
| XmlGroupBox: TGroupBox; | |
| XmlMemo: TMemo; | |
| XmlMemoTabSheet: TTabSheet; | |
| XmlOpenDialog: TOpenDialog; | |
| XmlPageControl: TPageControl; | |
| XmlViewTabSheet: TTabSheet; | |
| XmlWebBrowser: TWebBrowser; | |
| XPathLabeledEdit: TLabeledEdit; | |
| LoadXmlExample3Button: TButton; | |
| Panel1: TPanel; | |
| ShowTextInResultCheckBox: TCheckBox; | |
| ShowXmlInResultCheckBox: TCheckBox; | |
| procedure LoadXmlExample3ButtonClick(Sender: TObject); | |
| procedure FormCreate(Sender: TObject); | |
| procedure HistoryListBoxClick(Sender: TObject); | |
| procedure LoadXmlButtonClick(Sender: TObject); | |
| procedure LoadXmlExample1ButtonClick(Sender: TObject); | |
| procedure LoadXmlExample2ButtonClick(Sender: TObject); | |
| procedure RunXPathButtonClick(Sender: TObject); | |
| procedure ShowMsxml6VersionClick(Sender: TObject); | |
| procedure ShowNameSpacesButtonClick(Sender: TObject); | |
| procedure XmlPageControlChange(Sender: TObject); | |
| strict private | |
| FLogger: ILogger; | |
| private | |
| procedure AddSupportedVersion(Version: string; SupportedVersions: IStringListWrapper); | |
| procedure FillDomVendorComboBox; | |
| procedure LogDomVendorFeatures(const CurrentDomVendor: TDOMVendor; const Versions, Features: array of string); | |
| strict protected | |
| procedure AddXPathQueryToHistory; overload; virtual; | |
| procedure AddXPathQueryToHistory(const XPathQuery: string); overload; virtual; | |
| procedure ClearMemoAndShowXmlNamespaces; virtual; | |
| function GetLogger: ILogger; virtual; | |
| function GetXml: string; virtual; | |
| function GetXPathQuery: string; virtual; | |
| procedure LoadXmlAndShowNamespaces; virtual; | |
| procedure LoadXmlExample(const XPathQueries, XmlLines: array of string); virtual; | |
| procedure LogDomVendor(const CurrentDomVendor: TDOMVendor); virtual; | |
| procedure RunXPath; virtual; | |
| procedure SetXml(const Value: string); virtual; | |
| procedure SetXPathQuery(const Value: string); virtual; | |
| procedure UpdateXPathLabeledEditTextFromHistoryListBox; virtual; | |
| property Logger: ILogger read GetLogger; | |
| property Xml: string read GetXml write SetXml; | |
| property XPathQuery: string read GetXPathQuery write SetXPathQuery; | |
| end; | |
| var | |
| MainForm: TMainForm; | |
| implementation | |
| uses | |
| {$if CompilerVersion <= 18.5} // D2007 and less http://stackoverflow.com/a/1572163/29290 | |
| oxmldom, // OmniXML | |
| {$else} | |
| adomxmldom, // http://stackoverflow.com/a/1766687/29290 | |
| {$ifend} | |
| { up until Delphi 2009, msxml contains the import of C:\WINDOWS\SYSTEM\MSXML.DLL, | |
| as of Delphi 2010 it imports C:\WINDOWS\SYSTEM\MSXML6.DLL } | |
| {$if CompilerVersion >= 21.0} | |
| msxml, // Delphi 2010 and up: IXMLDOMSchemaCollection2 et al | |
| {$else} | |
| MSXML2_TLB, // Delphi < 2010: IXMLDOMSchemaCollection2 et al | |
| {$ifend} | |
| XmlHelperUnit, | |
| XMLDoc, | |
| XMLIntf, | |
| StringUtilsUnit, | |
| LoggersUnit, | |
| msxmlFactoryUnit, | |
| WebBrowserHelperUnit; | |
| {$R *.dfm} | |
| procedure TMainForm.FormCreate(Sender: TObject); | |
| begin | |
| FillDomVendorComboBox(); | |
| end; | |
| procedure TMainForm.HistoryListBoxClick(Sender: TObject); | |
| begin | |
| UpdateXPathLabeledEditTextFromHistoryListBox(); | |
| end; | |
| procedure TMainForm.LoadXmlButtonClick(Sender: TObject); | |
| begin | |
| LoadXmlAndShowNamespaces(); | |
| end; | |
| procedure TMainForm.LoadXmlExample1ButtonClick(Sender: TObject); | |
| begin | |
| LoadXmlExample([ | |
| '//bk:Book[position()<=2]', | |
| '//bk:Book[position()<=2]/*/text()' | |
| ], | |
| [ | |
| '<?xml version="1.0"?>', | |
| '<bk:Books xmlns:bk="http://myserver/myschemas/Books">', | |
| ' <bk:Book>', | |
| ' <bk:Title>Just XML</bk:Title>', | |
| ' </bk:Book>', | |
| ' <bk:Book>', | |
| ' <bk:Title>Professional XML</bk:Title>', | |
| ' </bk:Book>', | |
| ' <bk:Book>', | |
| ' <bk:Title>XML Step by Step</bk:Title>', | |
| ' </bk:Book>', | |
| ' <bk:Book>', | |
| ' <bk:Title>XML By Example</bk:Title>', | |
| ' </bk:Book>', | |
| '</bk:Books>' | |
| ]); | |
| end; | |
| procedure TMainForm.LoadXmlExample2ButtonClick(Sender: TObject); | |
| begin | |
| LoadXmlExample([ | |
| '//root', | |
| '//a:root', | |
| '//branch', | |
| '//a:branch', | |
| '//b:branch' | |
| ], | |
| [ | |
| '<?xml version="1.0"?>', | |
| '<root>', | |
| '<branch>branch</branch>', | |
| '<a:root xmlns:a="http://myserver.com">', | |
| '<a:branch>a-branch</a:branch>', | |
| '<b:branch xmlns:b="http://yourserver.com">', | |
| 'b-branch', | |
| '</b:branch>', | |
| '</a:root>', | |
| '</root>' | |
| ]); | |
| end; | |
| procedure TMainForm.RunXPathButtonClick(Sender: TObject); | |
| begin | |
| RunXPath(); | |
| end; | |
| procedure TMainForm.ShowMsxml6VersionClick(Sender: TObject); | |
| begin | |
| { | |
| Windows 2003 with MSXML 3: | |
| ————————– | |
| msxml3.dll: 8.100.1050.0 | |
| Error | |
| Exception "ENotSupportedException", at 0051351A: "msxml6.dll must be newer than version 6.20.1099.* (you need 6.30.*, 6.20.1103.*, 6.20.2003.0 or higher), but you have version msxml3.dll: 8.100.1050.0" | |
| windows XP with MSXML 4: | |
| ———————— | |
| msxml4.dll: 4.20.9818.0 | |
| Error | |
| Exception "ENotSupportedException", at 00513536: "msxml6.dll must be newer than version 6.20.1099.* (you need 6.30.*, 6.20.1103.*, 6.20.2003.0 or higher), but you have version msxml4.dll: 4.20.9818.0" | |
| Windows XP with MSXML 6 SP1: | |
| ———————— | |
| msxml6.dll: 6.10.1129.0 | |
| Error | |
| Exception "ENotSupportedException", at 00513536: "msxml6.dll must be newer than version 6.20.1099.* (you need 6.30.*, 6.20.1103.*, 6.20.2003.0 or higher), but you have version msxml6.dll: 6.10.1129.0" | |
| windows XP with MSXML 6 SP2 (latest): | |
| ———————— | |
| msxml6.dll: 6.20.1103.0 | |
| Windows 7 with MSXML 6 SP3: | |
| ————————– | |
| msxml6.dll: 6.30.7600.16385 | |
| } | |
| try | |
| Logger.Log(TmsxmlFactory.msxmlBestFileVersion.ToString()); | |
| TmsxmlFactory.AssertCompatibleMsxml6Version(); | |
| except | |
| on E: Exception do | |
| begin | |
| Logger.Log('Error'); | |
| Logger.Log(E); | |
| end; | |
| end; | |
| end; | |
| procedure TMainForm.ShowNameSpacesButtonClick(Sender: TObject); | |
| begin | |
| ClearMemoAndShowXmlNamespaces(); | |
| end; | |
| procedure TMainForm.XmlPageControlChange(Sender: TObject); | |
| begin | |
| if XmlPageControl.ActivePage = XmlViewTabSheet then | |
| XmlWebBrowser.LoadFromXmlString(Xml); | |
| end; | |
| procedure TMainForm.AddSupportedVersion(Version: string; SupportedVersions: IStringListWrapper); | |
| begin | |
| if Version = NullAsStringValue then | |
| SupportedVersions.Add('Any') | |
| else | |
| SupportedVersions.Add(Version); | |
| end; | |
| 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.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; | |
| procedure TMainForm.AddXPathQueryToHistory; | |
| begin | |
| AddXPathQueryToHistory(XPathQuery); | |
| end; | |
| procedure TMainForm.AddXPathQueryToHistory(const XPathQuery: string); | |
| begin | |
| if HistoryListBox.Items.IndexOf(XPathQuery) = -1 then | |
| HistoryListBox.Items.Add(XPathQuery); | |
| HistoryMemo.Lines.Add(XPathQuery); | |
| end; | |
| procedure TMainForm.LoadXmlExample3ButtonClick(Sender: TObject); | |
| begin | |
| LoadXmlExample([ // unique account numbers | |
| '/Accounts/Account[not(@Number=preceding-sibling::Account/@Number)]/@Number' | |
| ], | |
| [ | |
| '<?xml version="1.0"?>', | |
| '<Accounts>', | |
| ' <Account Number="1" DebitAmount="1000" Amount="2827561.95" />', | |
| ' <Account Number="225" DebitAmount="2000" Amount="12312.00" />', | |
| ' <Account Number="236" DebitAmount="London" Amount="457656.00" />', | |
| ' <Account Number="225" DebitAmount="London" Amount="23462.40" />', | |
| ' <Account Number="236" DebitAmount="Bangalore" Amount="2345345.00" />', | |
| '</Accounts>' | |
| ]); | |
| end; | |
| procedure TMainForm.ClearMemoAndShowXmlNamespaces; | |
| var | |
| DomDocument: IDOMDocument; | |
| DomNodeSelect: IDOMNodeSelect; | |
| NamespaceIDomNode: IDOMNode; | |
| NamespaceIDomNodeArray: IDOMNodeArray; | |
| PrefixWithDoubleQuotedNamespaceURI: string; | |
| begin | |
| try | |
| IDomNodeHelper.CreateDocumentAndDOMNodeSelect(Xml, DomDocument, DomNodeSelect); | |
| ResultsMemo.Clear; | |
| NamespaceIDomNodeArray := IDomNodeHelper.FindNamespaceDecls(DomDocument.documentElement); | |
| for NamespaceIDomNode in NamespaceIDomNodeArray do | |
| begin | |
| // Logger.Log('Prefix', NamespaceIDomNode.Prefix); // always xmlns | |
| // Logger.Log('LocalName', NamespaceIDomNode.LocalName); // the prefix | |
| // Logger.Log('NodeValue', string(NamespaceIDomNode.NodeValue)); // the URI | |
| PrefixWithDoubleQuotedNamespaceURI := Format('%s="%s"', [NamespaceIDomNode.NodeName, string(NamespaceIDomNode.NodeValue)]); | |
| Logger.Log(PrefixWithDoubleQuotedNamespaceURI); | |
| end; | |
| except | |
| on E: Exception do | |
| Logger.Log(E); | |
| end; | |
| end; | |
| function TMainForm.GetLogger: ILogger; | |
| begin | |
| if not Assigned(FLogger) then | |
| begin | |
| FLogger := TTeeLogger.Create([TStringsLogger.Create(ResultsMemo.Lines)]); | |
| end; | |
| Result := FLogger; | |
| end; | |
| function TMainForm.GetXml: string; | |
| begin | |
| Result := XmlMemo.Text; | |
| end; | |
| function TMainForm.GetXPathQuery: string; | |
| begin | |
| Result := XPathLabeledEdit.Text; | |
| end; | |
| procedure TMainForm.LoadXmlAndShowNamespaces; | |
| begin | |
| if XmlOpenDialog.Execute then | |
| begin | |
| Xml := LoadFromFile(XmlOpenDialog.FileName); | |
| ClearMemoAndShowXmlNamespaces(); | |
| end; | |
| end; | |
| procedure TMainForm.LoadXmlExample(const XPathQueries, XmlLines: array of string); | |
| var | |
| XmlLine: string; | |
| XPathQuery: string; | |
| begin | |
| XPathQuery := NullAsStringValue; | |
| HistoryListBox.Clear(); | |
| for XPathQuery in XPathQueries do | |
| AddXPathQueryToHistory(XPathQuery); | |
| XmlMemo.Clear(); | |
| for XmlLine in XmlLines do | |
| XmlMemo.Lines.Add(XmlLine); | |
| ClearMemoAndShowXmlNamespaces(); | |
| if HistoryListBox.Items.Count > 0 then | |
| begin | |
| HistoryListBox.ItemIndex := 0; | |
| UpdateXPathLabeledEditTextFromHistoryListBox(); | |
| // add a "splitter" line for better visual appearance | |
| if HistoryMemo.Lines.Count <> 0 then | |
| HistoryMemo.Lines.Add(NullAsStringValue); | |
| end; | |
| end; | |
| procedure TMainForm.LogDomVendor(const CurrentDomVendor: TDOMVendor); | |
| var | |
| CurrentDomVendorDescription: string; | |
| DocumentElement: IDOMElement; | |
| DomDocument: IDOMDocument; // xmldom.IDOMDocument is the plain XML DOM | |
| XmlDocument: IXMLDocument; // XMLIntf.IXMLDocument is the enrichted XML interface to the TComponent wrapper, which has a DOMDocument: IDOMDocument poperty, and allows obtaining XML from different sources (text, file, stream, etc) | |
| XmlDocumentInstance: TXMLDocument; // unit XMLDoc | |
| 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; // we get another reference here, since we loaded some XML now | |
| DocumentElement := DomDocument.DocumentElement; | |
| if Assigned(DocumentElement) then | |
| begin | |
| DOMNodeEx := DocumentElement as IDOMNodeEx; | |
| Logger.Log(DOMNodeEx.xml); | |
| end; | |
| if IDomNodeHelper.GetXmlDomDocument2(DomDocument, XMLDOMDocument2) then | |
| begin | |
| // XSLPattern versus XPath | |
| // see http://stackoverflow.com/questions/784745/accessing-comments-in-xml-using-xpath | |
| // XSLPattern is 0 based, but XPath is 1 based. | |
| 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'], | |
| //http://www.w3.org/TR/DOM-Level-3-Core/introduction.html#ID-Conformance | |
| //http://reference.sitepoint.com/javascript/DOMImplementation/hasFeature | |
| ['Core' | |
| ,'XML' | |
| ,'Events' | |
| ,'UIEvents' | |
| ,'MouseEvents' | |
| ,'TextEvents' | |
| ,'KeyboardEvents' | |
| ,'MutationEvents' | |
| ,'MutationNameEvents' | |
| ,'HTMLEvents' | |
| ,'LS' | |
| ,'LS-Async' | |
| ,'Validation' | |
| ,'XPath' | |
| ]); | |
| end; | |
| procedure TMainForm.RunXPath; | |
| var | |
| DomDocument: IDOMDocument; | |
| DomNode: IDOMNode; | |
| DomNodeEx: IDOMNodeEx; | |
| DomNodeList: IDOMNodeList; | |
| DomNodeSelect: IDOMNodeSelect; | |
| Index: Integer; | |
| Length: Integer; | |
| begin | |
| ClearMemoAndShowXmlNamespaces(); | |
| Logger.Log(''); | |
| try | |
| // Step 1: Load the XML and get references to the right interfaces | |
| IDomNodeHelper.CreateDocumentAndDOMNodeSelect(Xml, DomDocument, DomNodeSelect); | |
| // Step 2: Run the query with the helper (it will load perform the correct SelectionNamespaces first) | |
| DomNodeList := IDomNodeHelper.RunXPathQuery(DomDocument, XPathQuery); | |
| Length := DomNodeList.length; | |
| if Length = 0 then | |
| Logger.Log('No nodes returned from the XPathQuery query') | |
| else | |
| for Index := 0 to Length – 1 do | |
| begin | |
| DomNode := DomNodeList.item[Index]; | |
| Logger.Log('nodeName', Index, DomNode.nodeName); | |
| Logger.Log('nodeValue', Index, string(DomNode.nodeValue)); | |
| DomNodeEx := DomNode as IDOMNodeEx; | |
| if ShowXmlInResultCheckBox.Checked then | |
| begin | |
| Logger.Log('xml', Index, ''); | |
| Logger.Log(DomNodeEx.xml); | |
| end; | |
| if ShowTextInResultCheckBox.Checked then | |
| Logger.Log('text', Index, DomNodeEx.text); | |
| end; | |
| AddXPathQueryToHistory(); | |
| except | |
| on E: Exception do | |
| Logger.Log(E); | |
| end; | |
| end; | |
| procedure TMainForm.SetXml(const Value: string); | |
| begin | |
| XmlMemo.Text := Value; | |
| end; | |
| procedure TMainForm.SetXPathQuery(const Value: string); | |
| begin | |
| XPathLabeledEdit.Text := Value; | |
| end; | |
| procedure TMainForm.UpdateXPathLabeledEditTextFromHistoryListBox; | |
| var | |
| ItemIndex: Integer; | |
| begin | |
| ItemIndex := HistoryListBox.ItemIndex; | |
| if ItemIndex <> -1 then | |
| XPathLabeledEdit.Text := HistoryListBox.Items[ItemIndex]; | |
| end; | |
| end. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| program XPathTester; | |
| uses | |
| Forms, | |
| MainFormUnit in '..\src\MainFormUnit.pas' {MainForm}, | |
| LoggerUnit in '..\..\..\..\bo.Logging\LoggerUnit.pas', | |
| StringListWrapperUnit in '..\..\..\..\bo.Text\StringListWrapperUnit.pas', | |
| ReporterUnit in '..\..\..\..\bo.Logging\ReporterUnit.pas', | |
| ReportProxyUnit in '..\..\..\..\bo.Logging\ReportProxyUnit.pas', | |
| RecordTypeInfoUnit in '..\..\..\..\bo.TypeInfo\RecordTypeInfoUnit.pas', | |
| SetTypeInfoUnit in '..\..\..\..\bo.TypeInfo\SetTypeInfoUnit.pas', | |
| EnumTypeInfoUnit in '..\..\..\..\bo.TypeInfo\EnumTypeInfoUnit.pas', | |
| WebBrowserHelperUnit in '..\..\..\..\bo.Helpers\WebBrowserHelperUnit.pas', | |
| LoggersUnit in '..\..\..\..\bo.Logging\LoggersUnit.pas', | |
| StringUtilsUnit in '..\..\..\..\bo.Text\StringUtilsUnit.pas', | |
| XmlHelperUnit in '..\..\..\..\bo.XML\XmlHelperUnit.pas', | |
| ComponentHelperUnit in '..\..\..\..\bo.Helpers\ComponentHelperUnit.pas', | |
| ReportingLoggerUnit in '..\..\..\..\bo.Logging\ReportingLoggerUnit.pas', | |
| MakeResourceUrlUnit in '..\..\..\..\bo.Helpers\MakeResourceUrlUnit.pas', | |
| ReportersUnit in '..\..\..\..\bo.Logging\ReportersUnit.pas', | |
| msxmlFactoryUnit in '..\..\..\..\bo.XML\msxmlFactoryUnit.pas', | |
| ReportProxyInterfaceUnit in '..\..\..\..\bo.Logging\ReportProxyInterfaceUnit.pas', | |
| LoggerInterfaceUnit in '..\..\..\..\bo.Logging\LoggerInterfaceUnit.pas', | |
| FileVersionUnit in '..\..\..\..\bo.System\FileVersionUnit.pas', | |
| XMLDOMParseErrorToStringUnit in '..\..\..\..\bo.XML\XMLDOMParseErrorToStringUnit.pas', | |
| DbWinUnit in '..\..\..\..\bo.DebugView\DbWinUnit.pas', | |
| DebuggingUnit in '..\..\..\..\bo.Debugging\DebuggingUnit.pas', | |
| MSXML2_TLB in '..\..\..\..\bo.XML\MSXML2_TLB.pas', | |
| DictionaryUnit in '..\..\..\..\bo.Containers\DictionaryUnit.pas'; | |
| {$R *.res} | |
| begin | |
| Application.Initialize; | |
| Application.MainFormOnTaskbar := True; | |
| Application.CreateForm(TMainForm, MainForm); | |
| Application.Run; | |
| end. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |
| <PropertyGroup> | |
| <ProjectGuid>{f88f26c2-1ea0-45c4-b849-6446bf017362}</ProjectGuid> | |
| <MainSource>XPathTester.dpr</MainSource> | |
| <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> | |
| <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> | |
| <DCC_DCCCompiler>DCC32</DCC_DCCCompiler> | |
| <DCC_DependencyCheckOutputName>..\bin\XPathTester.exe</DCC_DependencyCheckOutputName> | |
| </PropertyGroup> | |
| <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> | |
| <Version>7.0</Version> | |
| <DCC_DebugInformation>False</DCC_DebugInformation> | |
| <DCC_LocalDebugSymbols>False</DCC_LocalDebugSymbols> | |
| <DCC_SymbolReferenceInfo>0</DCC_SymbolReferenceInfo> | |
| <DCC_Define>RELEASE</DCC_Define> | |
| </PropertyGroup> | |
| <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> | |
| <Version>7.0</Version> | |
| <DCC_Define>DEBUG</DCC_Define> | |
| <DCC_ExeOutput>..\bin</DCC_ExeOutput> | |
| <DCC_DcuOutput>..\lib</DCC_DcuOutput> | |
| <DCC_ObjOutput>..\lib</DCC_ObjOutput> | |
| <DCC_HppOutput>..\lib</DCC_HppOutput> | |
| <DCC_BplOutput>..\lib</DCC_BplOutput> | |
| <DCC_DcpOutput>..\lib</DCC_DcpOutput> | |
| <DCC_UnitSearchPath>$(BDS)\lib\Debug;$(BDS)\Lib\Debug\Indy10;$(BDS)\RaveReports\Lib;C:\EyePoint\version1\src\JVCL\jcl\lib\d11\debug</DCC_UnitSearchPath> | |
| <DCC_ResourcePath>$(BDS)\lib\Debug;$(BDS)\Lib\Debug\Indy10;$(BDS)\RaveReports\Lib;C:\EyePoint\version1\src\JVCL\jcl\lib\d11\debug</DCC_ResourcePath> | |
| <DCC_ObjPath>$(BDS)\lib\Debug;$(BDS)\Lib\Debug\Indy10;$(BDS)\RaveReports\Lib;C:\EyePoint\version1\src\JVCL\jcl\lib\d11\debug</DCC_ObjPath> | |
| <DCC_IncludePath>$(BDS)\lib\Debug;$(BDS)\Lib\Debug\Indy10;$(BDS)\RaveReports\Lib;C:\EyePoint\version1\src\JVCL\jcl\lib\d11\debug</DCC_IncludePath> | |
| <DCC_Optimize>False</DCC_Optimize> | |
| <DCC_GenerateStackFrames>True</DCC_GenerateStackFrames> | |
| </PropertyGroup> | |
| <ProjectExtensions> | |
| <Borland.Personality>Delphi.Personality</Borland.Personality> | |
| <Borland.ProjectType>VCLApplication</Borland.ProjectType> | |
| <BorlandProject> | |
| <BorlandProject><Delphi.Personality><Parameters><Parameters Name="UseLauncher">False</Parameters><Parameters Name="LoadAllSymbols">True</Parameters><Parameters Name="LoadUnspecifiedSymbols">False</Parameters></Parameters><VersionInfo><VersionInfo Name="IncludeVerInfo">False</VersionInfo><VersionInfo Name="AutoIncBuild">False</VersionInfo><VersionInfo Name="MajorVer">1</VersionInfo><VersionInfo Name="MinorVer">0</VersionInfo><VersionInfo Name="Release">0</VersionInfo><VersionInfo Name="Build">0</VersionInfo><VersionInfo Name="Debug">False</VersionInfo><VersionInfo Name="PreRelease">False</VersionInfo><VersionInfo Name="Special">False</VersionInfo><VersionInfo Name="Private">False</VersionInfo><VersionInfo Name="DLL">False</VersionInfo><VersionInfo Name="Locale">6153</VersionInfo><VersionInfo Name="CodePage">1252</VersionInfo></VersionInfo><VersionInfoKeys><VersionInfoKeys Name="CompanyName"></VersionInfoKeys><VersionInfoKeys Name="FileDescription"></VersionInfoKeys><VersionInfoKeys Name="FileVersion">1.0.0.0</VersionInfoKeys><VersionInfoKeys Name="InternalName"></VersionInfoKeys><VersionInfoKeys Name="LegalCopyright"></VersionInfoKeys><VersionInfoKeys Name="LegalTrademarks"></VersionInfoKeys><VersionInfoKeys Name="OriginalFilename"></VersionInfoKeys><VersionInfoKeys Name="ProductName"></VersionInfoKeys><VersionInfoKeys Name="ProductVersion">1.0.0.0</VersionInfoKeys><VersionInfoKeys Name="Comments"></VersionInfoKeys></VersionInfoKeys><Source><Source Name="MainSource">XPathTester.dpr</Source></Source></Delphi.Personality></BorlandProject></BorlandProject> | |
| </ProjectExtensions> | |
| <Import Project="$(MSBuildBinPath)\Borland.Delphi.Targets" /> | |
| <ItemGroup> | |
| <DelphiCompile Include="XPathTester.dpr"> | |
| <MainSource>MainSource</MainSource> | |
| </DelphiCompile> | |
| <DCCReference Include="..\..\..\..\bo.Containers\DictionaryUnit.pas" /> | |
| <DCCReference Include="..\..\..\..\bo.Debugging\DebuggingUnit.pas" /> | |
| <DCCReference Include="..\..\..\..\bo.DebugView\DbWinUnit.pas" /> | |
| <DCCReference Include="..\..\..\..\bo.Helpers\ComponentHelperUnit.pas" /> | |
| <DCCReference Include="..\..\..\..\bo.Helpers\MakeResourceUrlUnit.pas" /> | |
| <DCCReference Include="..\..\..\..\bo.Helpers\WebBrowserHelperUnit.pas" /> | |
| <DCCReference Include="..\..\..\..\bo.Logging\LoggerInterfaceUnit.pas" /> | |
| <DCCReference Include="..\..\..\..\bo.Logging\LoggersUnit.pas" /> | |
| <DCCReference Include="..\..\..\..\bo.Logging\LoggerUnit.pas" /> | |
| <DCCReference Include="..\..\..\..\bo.Logging\ReportersUnit.pas" /> | |
| <DCCReference Include="..\..\..\..\bo.Logging\ReporterUnit.pas" /> | |
| <DCCReference Include="..\..\..\..\bo.Logging\ReportingLoggerUnit.pas" /> | |
| <DCCReference Include="..\..\..\..\bo.Logging\ReportProxyInterfaceUnit.pas" /> | |
| <DCCReference Include="..\..\..\..\bo.Logging\ReportProxyUnit.pas" /> | |
| <DCCReference Include="..\..\..\..\bo.System\FileVersionUnit.pas" /> | |
| <DCCReference Include="..\..\..\..\bo.Text\StringListWrapperUnit.pas" /> | |
| <DCCReference Include="..\..\..\..\bo.Text\StringUtilsUnit.pas" /> | |
| <DCCReference Include="..\..\..\..\bo.TypeInfo\EnumTypeInfoUnit.pas" /> | |
| <DCCReference Include="..\..\..\..\bo.TypeInfo\RecordTypeInfoUnit.pas" /> | |
| <DCCReference Include="..\..\..\..\bo.TypeInfo\SetTypeInfoUnit.pas" /> | |
| <DCCReference Include="..\..\..\..\bo.XML\MSXML2_TLB.pas" /> | |
| <DCCReference Include="..\..\..\..\bo.XML\msxmlFactoryUnit.pas" /> | |
| <DCCReference Include="..\..\..\..\bo.XML\XMLDOMParseErrorToStringUnit.pas" /> | |
| <DCCReference Include="..\..\..\..\bo.XML\XmlHelperUnit.pas" /> | |
| <DCCReference Include="..\src\MainFormUnit.pas"> | |
| <Form>MainForm</Form> | |
| </DCCReference> | |
| </ItemGroup> | |
| </Project> |






Leave a comment