1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 2003-2016. 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 <code>xmerl_xpath</code>
% it is possible to write XSLT like transforms in Erlang.
%
% <p>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.
% </p>
% <p>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.</p>
% <p>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 <a href="xmerl_xs_examples.html">Tutorial</a>.
% </p>
-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.
%%
%% <p>Example, original XSLT:</p><br/><pre>
%% <xsl:template match="doc/title">
%% <h1>
%% <xsl:apply-templates/>
%% </h1>
%% </xsl:template>
%% </pre>
%%
%% <p>becomes in Erlang:</p><br/><pre>
%% template(E = #xmlElement{ parents=[{'doc',_}|_], name='title'}) ->
%% ["<h1>",
%% xslapply(fun template/1, E),
%% "</h1>"];
%% </pre>
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 = term()
%%
%% @doc Concatenates all text nodes within the tree.
%%
%% <p>Example:</p><br/><pre>
%% <xsl:template match="title">
%% <div align="center">
%% <h1><xsl:value-of select="." /></h1>
%% </div>
%% </xsl:template>
%% </pre>
%%
%% <p>becomes:</p><br/> <pre>
%% template(E = #xmlElement{name='title'}) ->
%% ["<div align="center"><h1>",
%% value_of(select(".", E)), "</h1></div>"]
%% </pre>
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:
%% <br/><code>template(E) -> built_in_rules(fun template/1, E)</code>.
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) ->[].
|