2013-06-17 3 views
4

У меня есть рабочий код с использованием класса TXMLDocument Delphi и использование метода TransformNode для выполнения XSLT-перевода.Доступ к IXMLDOMDocument2 через TXMLDocument?

Но мне нужно, чтобы включить функции XSLT JavaScript (<msxml:script> тегов) и - после того, как много прибегая к помощи - это означает, что мне нужно, чтобы установить AllowXsltScript свойства IXMLDOMDocument2 к истине.

http://msdn.microsoft.com/en-us/library/windows/desktop/ms760290(v=vs.85).aspx

Я достиг этого успешно - но только путем изменения источника функции библиотеки Delphi CreateDOMDocument в msxmldom.pas.

function CreateDOMDocument: IXMLDOMDocument; 
var doc :IXMLDOMDocument2; 
begin 

    doc := TryObjectCreate([CLASS_DOMDocument60, CLASS_DOMDocument40, CLASS_DOMDocument30, 
    CLASS_DOMDocument26, msxml.CLASS_DOMDocument]) as IXMLDOMDocument2; 
    if not Assigned(doc) then 
    raise DOMException.Create(SMSDOMNotInstalled); 
    doc.setProperty('AllowXsltScript', true); // Allow XSLT scripts!! 
    Result := doc; 
end; 

Очевидно, что это далеко не удовлетворительны, - так как я могу получить доступ к IXMLDOMDocument2 объектов без модифицирующих код библиотеки ??

+0

Не можете просто позвонить 'CoCreateInstance' себя и сделать' IXMLDOMDocument2'? –

+1

@DavidHeffernan - проблема в том, что у меня есть куча существующего кода, основанного на TXMLDocument, с которым я не хочу общаться. Если бы я делал это с чистого листа, я бы, вероятно, не использовал MSXML! – Roddy

ответ

4

Вы можете переопределить функцию создания с помощью переменной MSXMLDOMDocumentCreate:

unit Unit27; 

interface 

uses 
    xmldoc, xmlintf, msxml, msxmldom, Forms, SysUtils, 
    ActiveX, ComObj, XmlDom, XmlConst, 
    Windows, Messages, Classes, Controls, StdCtrls; 

type 
    TForm1 = class(TForm) 
    procedure FormCreate(Sender: TObject); 
    private 
    { Private declarations } 
    public 
    { Public declarations } 
    end; 

var 
    Form1: TForm1; 

implementation 

{$R *.dfm} 

function TryObjectCreate(const GuidList: array of TGuid): IUnknown; 
var 
    I: Integer; 
    Status: HResult; 
begin 
    Status := S_OK; 
    for I := Low(GuidList) to High(GuidList) do 
    begin 
    Status := CoCreateInstance(GuidList[I], nil, CLSCTX_INPROC_SERVER or 
     CLSCTX_LOCAL_SERVER, IDispatch, Result); 
    if Status = S_OK then Exit; 
    end; 
    OleCheck(Status); 
end; 

function CreateDOMDocument2: IXMLDOMDocument; 

var 
    Doc2 : IXMLDOMDocument2; 

begin 
    Doc2 := TryObjectCreate([CLASS_DOMDocument60, CLASS_DOMDocument40, CLASS_DOMDocument30, 
    CLASS_DOMDocument26, msxml.CLASS_DOMDocument]) as IXMLDOMDocument2; 
    if not Assigned(Doc2) then 
    raise DOMException.Create(SMSDOMNotInstalled); 
    Doc2.setProperty('AllowXsltScript', true); 
    Result := Doc2; 
end; 


procedure TForm1.FormCreate(Sender: TObject); 

var 
Doc : IXMLDocument; 

begin 
Doc := TXMLDocument.Create(nil); 
Doc.LoadFromFile('c:\temp\test.xml'); 
end; 


initialization 
MSXMLDOMDocumentCreate := CreateDOMDocument2; 
end. 
+0

@Roddy: Изменен образец кода, это должно работать (проверено на delphi XE) – whosrdaddy

+0

Гораздо лучше ;-) Я немного упростил это, используя существующую функцию CreateDomdDocument: 'function CreateDOMDocument2: IXMLDOMDocument; начало результат: = CreateDomDocument; (результат как IXMLDOMDocument2) .setProperty ('AllowXsltScript', true); end; ' – Roddy

+0

Я подозреваю, что это лучшее, что мы можем получить, но одна проблема заключается в том, что это позволяет сценарии для * всех * IXMLDocuments, независимо. – Roddy

3

Обратите внимание, что в XE3 и выше, MSXMLDOMDocumentCreate осуждаются в пользу подклассов TMSXMLDOMDocumentFactory и переопределение этого CreateDOMDocument функции. Для дальнейшего использования, вот пример для XE3 и xe4:

interface 

type 
    TMSXMLDOMDocument2Factory = class(TMSXMLDOMDocumentFactory) 
    public 
    class function CreateDOMDocument: IXMLDOMDocument; override; 
    end; 

implementation 

{ TMSXMLDOMDocument2Factory } 

class function TMSXMLDOMDocument2Factory.CreateDOMDocument: IXMLDOMDocument; 
begin 
    Result := inherited; 
    if not Assigned(Result) then 
    raise DOMException.Create(SMSDOMNotInstalled); 
    AddDOMProperty('AllowXsltScript', True); 
    SetDOMProperties(Result as IXMLDOMDocument2); 
end; 

initialization 
    MSXMLDOMDocumentFactory := TMSXMLDOMDocument2Factory; 

end. 
+1

Ну, похоже, для XE3/4 вам вообще не нужно подкласса - вы просто назовете 'Xml.Win.msxmldom.MSXMLDOMDocumentFactory.AddDOMProperty ('AllowXsltScript', True);' См. Наб. wiki: http://docwiki.embarcadero.com/Libraries/XE4/en/Xml.Win.msxmldom.TMSXMLDOMDocumentFactory.AddDOMProperty – Roddy

+0

@Roddy: Я специально ссылался (как я сказал в тексте выше кода) на 'MSXMLDOMDocumentCreate 'теперь не рекомендуется, и показывается замена для него. Поскольку мой код также использует 'AddDOMProperty', он должен быть довольно ясным, я знал, что он есть. ;-) Вопрос о том, как получить доступ к 'IXMLDOMDocument2' через' TXMLDocument', и это часть, которую я адресул, а не конкретную настройку свойства DOM второго уровня. –

+0

Ken, Спасибо: да, я ценю это: я согласен с тем, что мой вопрос, возможно, был немного ошибочным. поскольку мои исследования привели меня к IXMLDOMDocument2 как к способу * only * для установки свойств DOM второго уровня. С XE3/4 это уже не так. (На первый взгляд на ваш код я предположил, что AddDOMProperty должен быть защищен и, следовательно, требует подкласса) – Roddy