XslTransform a XslCompiledTransform

Wraz z .NET Framework 2.0 klasa XslTransform została oznaczona jako "obsolete" co oznacza, że nie ma dalszych planów rozwoju tej klasy i, że może ona zostać usunięta w nowych wersjach platformy .NET Framework. Miejsce klasy XslTransform zajęła klasa XslCompiledTransform. W przeciwieństwie do klasy XslTransform klasa XslCompiledTransform jest cały czas udoskonalana co oznacza, że praktycznie każda nowa wersja platformy .NET Framework (a także Service Packi) zawierają udoskonalenia i poprawki znalezionych w tej klasie błędów.

Od czasu opublikowania .NET Framework 2.0 minęło sporo (będzie ponad 3 lata?) czasu więc artykuł może się wydawać odrobinę nieświeży. Jednak praktyka pokazuje, że mimo długiego czasu (i kilku nowszych wersji .NET Frameworka) wiele osób wciąż używa nowej klasy niezgodnie z intencjami. W dużej mierze dotyczy to aplikacji przeniesionych z .NET Framework 1.1. W mojej opinii było to po prostu zbyt proste. Kompilacja aplikacji z bibliotekami 2.0 zaczęła nagle zgłaszać ostrzeżenia, że klasa XslTransform jest "obsolete". Wystarczyło tylko zmienić nazwe klasy oraz dodać dodatkowe parametry do metody Load (XmlResolver o ile dobrze pamiętam) i problem z głowy. Można więc było się pozbyć ostrzeżeń zwracanych przez kompilator praktycznie bez żadnych dodatkowych zmian w aplikacji. Ponieważ było to bardzo proste większość osób nawet nie probowała znaleźć różnicy pomiędzy oboma API. Nowe aplikacje też nierzadko używają klasy XslCompiledTransform w sposób niezgodny z zaleceniami projektantów i autorów.

Jaka jest więc główna różnica pomiędzy klasą XslTransform a XslCompiledTransform? Przede wszystkim klasa XslTransform interpretuje arkusz Xslt podczas transformacji podczas gdy klasa XslCompiledTransform KOMPILUJE arkusz xslt do IL (ang. intermediate language). Tak, arkusz xslt jest kompilowany bezpośrednio do niskopoziomowego języka wykonywanego bezpośrednio przez CLR (Common Language Runtime) - tak jak to ma miejsce w przypadku innych języków .NETowych takich jak C# czy VB.NET. Kompilacja następuje przy wywołaniu metody XslCompiledTransform.Load(). Co z tego tak naprawdę wynika? Otóż w przypadku klasy XslTransform pierwsza transformacja wykonuje się mniej więcej tyle samo co każda następna - arkusz jest interpretowany za każdym razem od nowa. Natomiast w przypadku klasy XslCompiledTransform załadowanie arkusza xslt trwa co prawda dłużej niż to miało miejsce dla klasy XslTransform ale transformacje są o wiele szybsze. Transformacja w tym przypadku to przecież tylko wykonywanie "czystego" skompilowanego już kodu. Ostateczna konkluzja jest więc taka, że po załadowaniu arkusza xslt do obiektu klasy XslCompiledTransform nie warto tego obiektu likwidować! Aplikacje ładujące arkusz (nierzadko w pętli), transformujące dokument Xml  oraz usuwające obiekt XslCompiledTransform, mogą mieć de facto o wiele gorszą wydajność niż gdyby używały klasy XslTransform. Przyczyną jest oczywiście czas potrzebny na skompilowanie - za każdym razem od nowa - arkusza xslt. Zamiast tego aplikacje powinny przechowywać (cache'ować) obiekty XslCompiledTransform po załadowaniu arkusza xslt i wykorzystywać je ponownie jeśli zachodzi potrzeba transformacji za pomocą tego samego arkusza xslt. W ten sposób można osiągnąć maksymalną wydajność transformacji.

(Inną dużą różnicą (będącą jednocześnie konsekwencją kompilacji arkusza xslt do IL) pomiędzy oboma klasami jest możliwość skompilowania za pomocą klasy XslCompiledTransform arkuszy xslt do wersji "debug" i debuggowanie ich w MS Visual Studio - wersja 2005 i nowsze - tak jak innych aplikacji napisanych w języku C# czy VB.NET).