File: xml_iter.ml

package info (click to toggle)
tyxml 3.0.0-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 884 kB
  • ctags: 5,290
  • sloc: ml: 14,771; makefile: 184; sh: 22
file content (187 lines) | stat: -rw-r--r-- 6,961 bytes parent folder | download | duplicates (2)
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
(* TyXML
 * http://www.ocsigen.org/tyxml
 * Copyright (C) 2004 Thorsten Ohl <ohl@physik.uni-wuerzburg.de>
 * Copyright (C) 2011 Pierre Chambart, Grégoire Henry
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, with linking exception;
 * either version 2.1 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02111-1307, USA.
 *)

module Make(Xml : Xml_sigs.Iterable) = struct

  open Xml

(** Iterators *)

  let amap1 f n =
    match content n with
    | Empty | Comment _ | PCDATA _ | EncodedPCDATA _ | Entity _ -> n
    | Leaf (name, attribs) -> leaf ~a:(f name attribs) name
    | Node (name, attribs, elts) -> node ~a:(f name attribs) name elts

  let rec amap f n =
    match content n with
    | Empty | Comment _ | PCDATA _ | EncodedPCDATA _ | Entity _ -> n
    | Leaf (name, attribs) -> leaf ~a:(f name attribs) name
    | Node (name, attribs, elts) ->
	node ~a:(f name attribs) name (List.map (amap f) elts)

  let rec add_float_attrib name value = function
    | [] -> [float_attrib name value]
    | head :: tail when aname head = name ->
	float_attrib name value :: tail
    | head :: tail -> head :: add_float_attrib name value tail

  let rec map_float_attrib is_attrib f l =
    let aux head = match acontent head with
    | AFloat value when is_attrib (aname head) -> float_attrib (aname head) (f value)
    | _ -> head in
    List.map aux l

  let rec add_int_attrib name value = function
    | [] -> [int_attrib name value]
    | head :: tail when aname head = name ->
	int_attrib name value :: tail
    | head :: tail -> head :: add_int_attrib name value tail

  let rec rm_attrib is_attrib = function
    | [] -> []
    | head :: tail when is_attrib (aname head) -> rm_attrib is_attrib tail
    | head :: tail -> head :: rm_attrib is_attrib tail

  let rec map_int_attrib is_attrib f l =
    let aux head = match acontent head with
    | AInt value when is_attrib (aname head) -> int_attrib (aname head) (f value)
    | _ -> head in
    List.map aux l

  let rec add_string_attrib name value = function
    | [] -> [string_attrib name value]
    | head :: tail when aname head = name ->
	string_attrib name value :: tail
    | head :: tail -> head :: add_string_attrib name value tail

  let rec map_string_attrib is_attrib f l =
    let aux head = match acontent head with
    | AStr value when is_attrib (aname head) -> string_attrib (aname head) (f value)
    | _ -> head in
    List.map aux l

  let rec add_space_sep_attrib name value = function
    | [] -> [space_sep_attrib name [value]]
    | head :: tail ->
	match acontent head with
	| AStrL (Space, values') when aname head = name ->
	    space_sep_attrib name (value :: values') :: tail
	| _ when aname head = name ->
	    space_sep_attrib name [value] :: tail
	| _ -> head :: add_space_sep_attrib name value tail

  let rec add_comma_sep_attrib name value = function
    | [] -> [comma_sep_attrib name [value]]
    | head :: tail ->
	match acontent head with
	| AStrL (Comma, values') when aname head = name ->
	    comma_sep_attrib name (value :: values') :: tail
	| _ when aname head = name ->
	    comma_sep_attrib name [value] :: tail
	| _ -> head :: add_comma_sep_attrib name value tail

  let rec rm_attrib_from_list is_attrib is_value = function
    | [] -> []
    | head :: tail ->
	match acontent head with
	| AStrL (sep, values) when is_attrib (aname head) ->
	    begin match List.filter (fun v -> not (is_value v)) values with
	    | [] -> tail
	    | values' ->
		match sep with
		| Space -> space_sep_attrib (aname head) values' :: tail
		| Comma -> comma_sep_attrib (aname head) values' :: tail
	    end
	| _ -> head :: rm_attrib_from_list is_attrib is_value tail

  let rec map_string_attrib_in_list is_attrib f l =
    let aux head = match acontent head with
    | AStrL (sep, values) when is_attrib (aname head) ->
	begin match sep with
	| Comma -> comma_sep_attrib (aname head) (List.map f values)
	| Space -> space_sep_attrib (aname head) (List.map f values)
	end
    | _ -> head in
    List.map aux l

  let rec fold of_empty of_comment of_pcdata of_encodedpcdata of_entity
      of_leaf of_node n =
    match content n with
    | Empty -> of_empty ()
    | Comment s -> of_comment s
    | PCDATA s -> of_pcdata s
    | EncodedPCDATA s -> of_encodedpcdata s
    | Entity s -> of_entity s
    | Leaf (name, attribs) -> of_leaf name attribs
    | Node (name, attribs, elts) ->
	of_node name attribs
          (List.map (fold of_empty of_comment of_pcdata of_encodedpcdata of_entity of_leaf of_node) elts)

(* (* is this AT ALL useful??? *)
   let rec foldx of_empty of_comment of_pcdata of_entity of_leaf of_node update_state state = function
   | Empty -> of_empty ()
   | Comment s -> of_comment s
   | PCDATA s -> of_pcdata s
   | Entity s -> of_entity s
   | Leaf (name, attribs) -> of_leaf state name attribs
   | Node (name, attribs, elts) ->
   of_node state name attribs
   (List.map (foldx of_empty of_comment of_pcdata of_entity of_leaf of_node
   update_state (update_state name attribs state)) elts)
 *)

  let all_attribs access ?(is_elt = fun ename -> true) aname elt =
    let access' ename attribs =
      if is_elt ename then
	try [access aname attribs] with Not_found -> []
      else
	[] in
    fold (fun () -> []) (fun c -> []) (fun p -> []) (fun p -> []) (fun e -> []) access'
      (fun ename attribs elts -> access' ename attribs @ List.flatten elts)
      elt

  let all_entities elt =
    fold (fun () -> []) (fun c -> []) (fun p -> []) (fun p -> []) (fun e -> [e])
      (fun ename attribs -> []) (fun ename attribs elts -> List.flatten elts)
      elt

  let rec flatmap f = function
    | [] -> []
    | x :: rest -> f x @ flatmap f rest

  let translate root_leaf root_node sub_leaf sub_node update_state state n =
    let rec translate' state  n =
      match content n with
      | (Empty | Comment _ | PCDATA _ | EncodedPCDATA _ | Entity _) -> [n]
      | Leaf (name, attribs) ->
          sub_leaf state name attribs
      | Node (name, attribs, elts) ->
          sub_node state name attribs
            (flatmap (translate' (update_state name attribs state)) elts)
    in
    match content n with
    | (Empty | Comment _ | PCDATA _ | EncodedPCDATA _ | Entity _) -> n
    | Leaf (name, attribs) ->
	root_leaf name attribs
    | Node (name, attribs, elts) ->
	root_node name attribs (flatmap (translate' state) elts)

end