1
1
extern crate quick_xml;
2
2
extern crate yaml_rust;
3
3
4
- use std:: io:: Read ;
4
+ use std:: io:: { Read , Write , stdout } ;
5
5
use std:: fs:: File ;
6
+ use std:: path:: Path ;
6
7
use std:: env;
7
8
use std:: time:: Instant ;
8
9
use quick_xml:: Reader ;
9
10
use quick_xml:: events:: Event ;
10
11
use yaml_rust:: YamlLoader ;
12
+ use yaml_rust:: yaml:: Yaml ;
13
+
14
+ struct Table < ' a > {
15
+ path : String ,
16
+ file : Box < dyn Write > ,
17
+ columns : Vec < Column < ' a > >
18
+ }
19
+ impl < ' a > Table < ' a > {
20
+ fn new < ' b > ( path : & str , file : Option < & str > ) -> Table < ' b > {
21
+ Table {
22
+ path : String :: from ( path) ,
23
+ file : match file {
24
+ None => Box :: new ( stdout ( ) ) ,
25
+ Some ( ref file) => Box :: new ( File :: create ( & Path :: new ( file) ) . unwrap ( ) )
26
+ } ,
27
+ columns : Vec :: new ( )
28
+ }
29
+ }
30
+ }
11
31
12
- #[ derive( Debug ) ]
13
32
struct Column < ' a > {
14
33
name : String ,
15
34
path : String ,
16
35
value : String ,
17
36
convert : Option < & ' a str > ,
18
37
search : Option < & ' a str > ,
19
38
replace : Option < & ' a str > ,
39
+ consol : Option < & ' a str >
20
40
}
21
41
22
42
struct Geometry {
@@ -61,11 +81,27 @@ fn gml_to_ewkb(value: &mut String, geom: &Geometry) {
61
81
}
62
82
}
63
83
64
- fn main ( ) {
84
+ fn add_table < ' a > ( tables : & mut Vec < Table < ' a > > , rowpath : & str , outfile : Option < & str > , colspec : & ' a Vec < Yaml > ) {
85
+ tables. push ( Table :: new ( rowpath, outfile) ) ;
86
+ let table = tables. last_mut ( ) . unwrap ( ) ;
87
+ for col in colspec {
88
+ let name = col[ "name" ] . as_str ( ) . expect ( "Column has no 'name' entry in configuration file" ) ;
89
+ let colpath = col[ "path" ] . as_str ( ) . expect ( "Column has no 'path' entry in configuration file" ) ;
90
+ let convert = col[ "convert" ] . as_str ( ) ;
91
+ let search = col[ "search" ] . as_str ( ) ;
92
+ let replace = col[ "replace" ] . as_str ( ) ;
93
+ let consol = col[ "consol" ] . as_str ( ) ;
94
+ let mut path = String :: from ( rowpath) ;
95
+ path. push_str ( colpath) ;
96
+ table. columns . push ( Column { name : name. to_string ( ) , path, value : String :: new ( ) , convert, search, replace, consol } ) ;
97
+ }
98
+ }
99
+
100
+ fn main ( ) -> std:: io:: Result < ( ) > {
65
101
let args: Vec < _ > = env:: args ( ) . collect ( ) ;
66
102
if args. len ( ) != 3 {
67
103
eprintln ! ( "usage: {} <configfile> <xmlfile>" , args[ 0 ] ) ;
68
- return ;
104
+ return Ok ( ( ) ) ;
69
105
}
70
106
71
107
let mut config_str = String :: new ( ) ;
@@ -78,23 +114,14 @@ fn main() {
78
114
79
115
let mut path = String :: new ( ) ;
80
116
let mut buf = Vec :: new ( ) ;
81
-
82
117
let mut count = 0 ;
83
118
84
- let rowpath = config[ "rowpath" ] . as_str ( ) . expect ( "No valid 'rowpath' entry in configuration file" ) ;
85
- let colspec = config[ "columns" ] . as_vec ( ) . expect ( "No valid 'columns' array in configuration file" ) ;
86
- let mut columns = Vec :: new ( ) ;
87
-
88
- for col in colspec {
89
- let name = col[ "name" ] . as_str ( ) . expect ( "Column has no 'name' entry in configuration file" ) ;
90
- let colpath = col[ "path" ] . as_str ( ) . expect ( "Column has no 'path' entry in configuration file" ) ;
91
- let convert = col[ "convert" ] . as_str ( ) ;
92
- let search = col[ "search" ] . as_str ( ) ;
93
- let replace = col[ "replace" ] . as_str ( ) ;
94
- let mut path = String :: from ( rowpath) ;
95
- path. push_str ( colpath) ;
96
- columns. push ( Column { name : name. to_string ( ) , path, value : String :: new ( ) , convert, search, replace } ) ;
97
- }
119
+ let rowpath = config[ "path" ] . as_str ( ) . expect ( "No valid 'rowpath' entry in configuration file" ) ;
120
+ let colspec = config[ "cols" ] . as_vec ( ) . expect ( "No valid 'columns' array in configuration file" ) ;
121
+ let outfile = config[ "file" ] . as_str ( ) ;
122
+ let mut tables: Vec < Table > = Vec :: new ( ) ;
123
+ add_table ( & mut tables, rowpath, outfile, colspec) ;
124
+ let table = tables. first_mut ( ) . unwrap ( ) ;
98
125
99
126
let mut xmltotext = false ;
100
127
let mut text = String :: new ( ) ;
@@ -155,13 +182,13 @@ fn main() {
155
182
}
156
183
continue ;
157
184
}
158
- else if path == rowpath {
185
+ else if path == table . path {
159
186
count += 1 ;
160
187
}
161
- else if path. len ( ) > rowpath . len ( ) {
162
- for i in 0 ..columns. len ( ) {
163
- if path == columns[ i] . path {
164
- match columns[ i] . convert {
188
+ else if path. len ( ) > table . path . len ( ) {
189
+ for i in 0 ..table . columns . len ( ) {
190
+ if path == table . columns [ i] . path {
191
+ match table . columns [ i] . convert {
165
192
None => ( ) ,
166
193
Some ( "xml-to-text" ) => xmltotext = true ,
167
194
Some ( "gml-to-ewkb" ) => gmltoewkb = true ,
@@ -186,48 +213,64 @@ fn main() {
186
213
}
187
214
continue ;
188
215
}
189
- for i in 0 ..columns. len ( ) {
190
- if path == columns[ i] . path {
191
- columns[ i] . value . push_str ( & e. unescape_and_decode ( & reader) . unwrap ( ) . replace ( "\\ " , "\\ \\ " ) ) ;
216
+ for i in 0 ..table. columns . len ( ) {
217
+ if path == table. columns [ i] . path {
218
+ match table. columns [ i] . consol {
219
+ None => {
220
+ if !table. columns [ i] . value . is_empty ( ) {
221
+ eprintln ! ( "Column '{}' has multiple occurrences without a consolidation method; using 'first'" , table. columns[ i] . name) ;
222
+ break ;
223
+ }
224
+ } ,
225
+ Some ( "append" ) => {
226
+ if !table. columns [ i] . value . is_empty ( ) { table. columns [ i] . value . push ( ',' ) ; }
227
+ } ,
228
+ Some ( s) => {
229
+ eprintln ! ( "Column '{}' has invalid consolidation method {}" , table. columns[ i] . name, s) ;
230
+ break ;
231
+ }
232
+ }
233
+ table. columns [ i] . value . push_str ( & e. unescape_and_decode ( & reader) . unwrap ( ) . replace ( "\\ " , "\\ \\ " ) ) ;
234
+ break ;
192
235
}
193
236
}
194
237
} ,
195
238
Ok ( Event :: End ( _) ) => {
196
- if path == rowpath {
197
- for i in 0 ..columns. len ( ) {
198
- if i > 0 { print ! ( "\t " ) ; }
199
- if columns[ i] . value . is_empty ( ) { print ! ( "\\ N" ) ; }
239
+ if path == table . path {
240
+ for i in 0 ..table . columns . len ( ) {
241
+ if i > 0 { write ! ( table . file , "\t " ) ? ; }
242
+ if table . columns [ i] . value . is_empty ( ) { write ! ( table . file , "\\ N" ) ? ; }
200
243
else {
201
- if let ( Some ( s) , Some ( r) ) = ( columns[ i] . search , columns[ i] . replace ) {
202
- columns[ i] . value = columns[ i] . value . replace ( s, r) ;
244
+ if let ( Some ( s) , Some ( r) ) = ( table . columns [ i] . search , table . columns [ i] . replace ) {
245
+ table . columns [ i] . value = table . columns [ i] . value . replace ( s, r) ;
203
246
}
204
- print ! ( "{}" , columns[ i] . value) ;
205
- columns[ i] . value . clear ( ) ;
247
+ write ! ( table . file , "{}" , table . columns[ i] . value) ? ;
248
+ table . columns [ i] . value . clear ( ) ;
206
249
}
207
250
}
208
- println ! ( "" ) ;
251
+ writeln ! ( table . file ) ? ;
209
252
}
210
253
let i = path. rfind ( '/' ) . unwrap ( ) ;
211
254
let tag = path. split_off ( i) ;
212
255
if xmltotext {
213
256
text. push_str ( & format ! ( "<{}>" , tag) ) ;
214
- for i in 0 ..columns. len ( ) {
215
- if path == columns[ i] . path {
257
+ for i in 0 ..table . columns . len ( ) {
258
+ if path == table . columns [ i] . path {
216
259
xmltotext = false ;
217
- if let ( Some ( s) , Some ( r) ) = ( columns[ i] . search , columns[ i] . replace ) {
260
+ if let ( Some ( s) , Some ( r) ) = ( table . columns [ i] . search , table . columns [ i] . replace ) {
218
261
text = text. replace ( s, r) ;
219
262
}
220
- columns[ i] . value . push_str ( & text) ;
263
+ table . columns [ i] . value . push_str ( & text) ;
221
264
text. clear ( ) ;
222
265
break ;
223
266
}
224
267
}
225
268
}
226
269
else if gmltoewkb {
227
- for i in 0 ..columns. len ( ) {
228
- if path == columns[ i] . path {
270
+ for i in 0 ..table . columns . len ( ) {
271
+ if path == table . columns [ i] . path {
229
272
gmltoewkb = false ;
230
- gml_to_ewkb ( & mut columns[ i] . value , & gmlgeom) ;
273
+ gml_to_ewkb ( & mut table . columns [ i] . value , & gmlgeom) ;
231
274
gmlgeom. reset ( ) ;
232
275
break ;
233
276
}
@@ -241,4 +284,5 @@ fn main() {
241
284
buf. clear ( ) ;
242
285
}
243
286
eprintln ! ( "{} rows processed in {} seconds" , count, start. elapsed( ) . as_secs( ) ) ;
287
+ Ok ( ( ) )
244
288
}
0 commit comments