%% %% %CopyrightBegin% %% %% Copyright Ericsson AB 2003-2009. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. %% You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. %% %% %CopyrightEnd% %% %% Description : Implements XSLT like transformations in Erlang %% @doc % Erlang has similarities to XSLT since both languages % have a functional programming approach. Using xmerl_xpath % it is possible to write XSLT like transforms in Erlang. % %

XSLT stylesheets are often used when transforming XML % documents, to other XML documents or (X)HTML for presentation. % XSLT contains quite many % functions and learning them all may take some effort. % This document assumes a basic level of % understanding of XSLT. %

%

Since XSLT is based on a functional programming approach % with pattern matching and recursion it is possible to write % similar style sheets in Erlang. At least for basic % transforms. This % document describes how to use the XPath implementation together % with Erlangs pattern matching and a couple of functions to write % XSLT like transforms.

%

This approach is probably easier for an Erlanger but % if you need to use real XSLT stylesheets in order to "comply to % the standard" there is an adapter available to the Sablotron % XSLT package which is written i C++. % See also the Tutorial. %

-module(xmerl_xs). -export([xslapply/2, value_of/1, select/2, built_in_rules/2 ]). -include("xmerl.hrl"). %% @spec xslapply(Function, EList::list()) -> List %% Function = () -> list() %% @doc xslapply is a wrapper to make things look similar to %% xsl:apply-templates. %% %%

Example, original XSLT:


%% <xsl:template match="doc/title">
%%   <h1>
%%     <xsl:apply-templates/>
%%   </h1>
%% </xsl:template>
%% 
%% %%

becomes in Erlang:


%% template(E = #xmlElement{ parents=[{'doc',_}|_], name='title'}) ->
%%   ["<h1>",
%%    xslapply(fun template/1, E),
%%    "</h1>"];
%% 
xslapply(Fun, EList) when is_list(EList) -> lists:map( Fun, EList); xslapply(Fun, E = #xmlElement{})-> lists:map( Fun, E#xmlElement.content). %% @spec value_of(E) -> List %% E = unknown() %% %% @doc Concatenates all text nodes within the tree. %% %%

Example:


%% <xsl:template match="title">
%%   <div align="center">
%%     <h1><xsl:value-of select="." /></h1>
%%   </div>
%% </xsl:template>
%% 
%% %%

becomes:


%%  template(E = #xmlElement{name='title'}) ->
%%    ["<div align="center"><h1>", 
%%      value_of(select(".", E)), "</h1></div>"]
%% 
value_of(E)-> lists:reverse(xmerl_lib:foldxml(fun value_of1/2, [], E)). value_of1(#xmlText{}=T1, Accu)-> [xmerl_lib:export_text(T1#xmlText.value)|Accu]; value_of1(_, Accu) -> Accu. %% @spec select(String::string(),E)-> E %% %% @doc Extracts the nodes from the xml tree according to XPath. %% @see value_of/1 select(Str,E)-> xmerl_xpath:string(Str,E). %% @spec built_in_rules(Fun, E) -> List %% %% @doc The default fallback behaviour. Template funs should end with: %%
template(E) -> built_in_rules(fun template/1, E). built_in_rules(Fun, E = #xmlElement{})-> lists:map(Fun, E#xmlElement.content); built_in_rules(_Fun, E = #xmlText{}) -> xmerl_lib:export_text(E#xmlText.value); built_in_rules(_Fun, E = #xmlAttribute{}) -> E#xmlAttribute.value; built_in_rules(_Fun, _E) ->[].