[spatialite-tools] 01/01: Imported Upstream version 4.2.0

Bas Couwenberg sebastic at xs4all.nl
Mon Aug 4 01:35:20 UTC 2014


This is an automated email from the git hooks/post-receive script.

sebastic-guest pushed a commit to branch upstream
in repository spatialite-tools.

commit 2717972969204541096102491a55a5f0a84b0619
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Mon Aug 4 00:14:39 2014 +0200

    Imported Upstream version 4.2.0
---
 Makefile-static-MinGW     |   63 +-
 Makefile.am               |   21 +-
 Makefile.in               |  320 +++--
 aclocal.m4                |  381 +++---
 configure                 |   82 +-
 configure.ac              |    2 +-
 exif_loader.c             |    1 +
 shell.c                   |  111 +-
 spatialite_convert.c      |   85 +-
 spatialite_dxf.c          |    3 +-
 spatialite_gml.c          |    1 +
 spatialite_network.c      |    1 +
 spatialite_osm_filter.c   |    1 +
 spatialite_osm_map.c      |   31 +-
 spatialite_osm_net.c      |    1 +
 spatialite_osm_raw.c      |    1 +
 spatialite_tool.c         |    1 +
 spatialite_xml_collapse.c | 2408 ++++++++++++++++++++++++++++++++++++++
 spatialite_xml_load.c     | 2837 +++++++++++++++++++++++++++++++++++++++++++++
 spatialite_xml_print.c    | 1063 +++++++++++++++++
 20 files changed, 7105 insertions(+), 309 deletions(-)

diff --git a/Makefile-static-MinGW b/Makefile-static-MinGW
index b551367..46685de 100644
--- a/Makefile-static-MinGW
+++ b/Makefile-static-MinGW
@@ -10,7 +10,10 @@ all: ./static_bin/spatialite.exe ./static_bin/spatialite_tool.exe \
 	./static_bin/exif_loader.exe ./static_bin/spatialite_osm_net.exe \
 	./static_bin/spatialite_osm_map.exe ./static_bin/spatialite_gml.exe \
 	./static_bin/spatialite_osm_raw.exe ./static_bin/spatialite_osm_filter.exe \
-	./static_bin/spatialite_convert.exe ./static_bin/spatialite_dxf.exe
+	./static_bin/spatialite_convert.exe ./static_bin/spatialite_dxf.exe \
+	./static_bin/spatialite_xml_collapse.exe \
+	./static_bin/spatialite_xml_load.exe \
+	./static_bin/spatialite_xml_print.exe
 
 ./static_bin/spatialite.exe: shell.o 
 	$(GG) shell.o -o ./static_bin/spatialite.exe \
@@ -214,6 +217,55 @@ all: ./static_bin/spatialite.exe ./static_bin/spatialite_tool.exe \
 	-lm -lmsimg32 -lws2_32 -static-libstdc++ -static-libgcc 
 	strip --strip-all ./static_bin/spatialite_osm_filter.exe
 
+./static_bin/spatialite_xml_collapse.exe: spatialite_xml_collapse.o
+	$(GG) spatialite_xml_collapse.o -o ./static_bin/spatialite_xml_collapse.exe \
+	/usr/local/lib/libspatialite.a \
+	/usr/local/lib/libsqlite3.a \
+	/usr/local/lib/liblwgeom.a \
+	/usr/local/lib/libxml2.a \
+	/usr/local/lib/liblzma.a \
+	/usr/local/lib/libproj.a \
+	/usr/local/lib/libgeos_c.a \
+	/usr/local/lib/libgeos.a \
+	/usr/local/lib/libfreexl.a \
+	/usr/local/lib/libz.a \
+	/usr/local/lib/libiconv.a \
+	-lm -lmsimg32 -lws2_32 -static-libstdc++ -static-libgcc 
+	strip --strip-all ./static_bin/spatialite_xml_collapse.exe
+
+./static_bin/spatialite_xml_load.exe: spatialite_xml_load.o
+	$(GG) spatialite_xml_load.o -o ./static_bin/spatialite_xml_load.exe \
+	/usr/local/lib/libspatialite.a \
+	/usr/local/lib/libsqlite3.a \
+	/usr/local/lib/liblwgeom.a \
+	/usr/local/lib/libxml2.a \
+	/usr/local/lib/liblzma.a \
+	/usr/local/lib/libproj.a \
+	/usr/local/lib/libgeos_c.a \
+	/usr/local/lib/libgeos.a \
+	/usr/local/lib/libfreexl.a \
+	/usr/local/lib/libexpat.a \
+	/usr/local/lib/libz.a \
+	/usr/local/lib/libiconv.a \
+	-lm -lmsimg32 -lws2_32 -static-libstdc++ -static-libgcc 
+	strip --strip-all ./static_bin/spatialite_xml_load.exe
+
+./static_bin/spatialite_xml_print.exe: spatialite_xml_print.o
+	$(GG) spatialite_xml_print.o -o ./static_bin/spatialite_xml_print.exe \
+	/usr/local/lib/libspatialite.a \
+	/usr/local/lib/libsqlite3.a \
+	/usr/local/lib/liblwgeom.a \
+	/usr/local/lib/libxml2.a \
+	/usr/local/lib/liblzma.a \
+	/usr/local/lib/libproj.a \
+	/usr/local/lib/libgeos_c.a \
+	/usr/local/lib/libgeos.a \
+	/usr/local/lib/libfreexl.a \
+	/usr/local/lib/libz.a \
+	/usr/local/lib/libiconv.a \
+	-lm -lmsimg32 -lws2_32 -static-libstdc++ -static-libgcc 
+	strip --strip-all ./static_bin/spatialite_xml_print.exe
+
 shell.o: 
 	$(CC) $(CFLAGS) shell.c -c
 	
@@ -243,3 +295,12 @@ spatialite_osm_raw.o:
 
 spatialite_osm_filter.o:
 	$(CC) $(CFLAGS) spatialite_osm_filter.c -c
+
+spatialite_xml_collapse.o:
+	$(CC) $(CFLAGS) spatialite_xml_collapse.c -c
+
+spatialite_xml_load.o:
+	$(CC) $(CFLAGS) spatialite_xml_load.c -c
+
+spatialite_xml_print.o:
+	$(CC) $(CFLAGS) spatialite_xml_print.c -c
diff --git a/Makefile.am b/Makefile.am
index 0e719c7..d9a52aa 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -9,7 +9,10 @@ bin_PROGRAMS = spatialite \
 	spatialite_osm_filter \
 	spatialite_gml \
 	spatialite_convert \
-	spatialite_dxf
+	spatialite_dxf \
+	spatialite_xml_load \
+	spatialite_xml_collapse \
+	spatialite_xml_print
 else
 bin_PROGRAMS = spatialite \
 	spatialite_tool \
@@ -22,17 +25,23 @@ bin_PROGRAMS = spatialite \
 	spatialite_osm_filter \
 	spatialite_gml \
 	spatialite_convert \
-	spatialite_dxf
+	spatialite_dxf \
+	spatialite_xml_load \
+	spatialite_xml_collapse \
+	spatialite_xml_print
 endif
 
-INCLUDES = @CFLAGS@
-INCLUDES += -I$(top_srcdir)
+AM_CPPFLAGS = @CFLAGS@
+AM_CPPFLAGS += -I$(top_srcdir)
 
 spatialite_SOURCES = shell.c
 spatialite_tool_SOURCES = spatialite_tool.c
 spatialite_network_SOURCES = spatialite_network.c
 shp_doctor_SOURCES = shp_doctor.c
 exif_loader_SOURCES = exif_loader.c
+spatialite_xml_load_SOURCES = spatialite_xml_load.c
+spatialite_xml_collapse_SOURCES = spatialite_xml_collapse.c
+spatialite_xml_print_SOURCES = spatialite_xml_print.c 
 if NO_READOSM
 else
 spatialite_osm_net_SOURCES = spatialite_osm_net.c
@@ -54,6 +63,10 @@ spatialite_gml_LDADD = @LIBSPATIALITE_LIBS@ \
 spatialite_LDADD = @LIBSPATIALITE_LIBS@ \
 	@LIBFREEXL_LIBS@ \
 	@READLINE_LIBS@
+spatialite_xml_load_LDADD = @LIBSPATIALITE_LIBS@ \
+	-lexpat
+spatialite_xml_collapse_LDADD = @LIBSPATIALITE_LIBS@
+spatialite_xml_print_LADD = @LIBSPATIALIATE_LIBS@
 LDADD = @LIBSPATIALITE_LIBS@ \
 	@LIBFREEXL_LIBS@
 
diff --git a/Makefile.in b/Makefile.in
index e91a652..c5c87bf 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.12.2 from Makefile.am.
+# Makefile.in generated by automake 1.13.4 from Makefile.am.
 # @configure_input@
 
-# Copyright (C) 1994-2012 Free Software Foundation, Inc.
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
 
 # This Makefile.in is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -15,23 +15,51 @@
 @SET_MAKE@
 
 VPATH = @srcdir@
-am__make_dryrun = \
-  { \
-    am__dry=no; \
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
     case $$MAKEFLAGS in \
       *\\[\ \	]*) \
-        echo 'am--echo: ; @echo "AM"  OK' | $(MAKE) -f - 2>/dev/null \
-          | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
-      *) \
-        for am__flg in $$MAKEFLAGS; do \
-          case $$am__flg in \
-            *=*|--*) ;; \
-            *n*) am__dry=yes; break;; \
-          esac; \
-        done;; \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
     esac; \
-    test $$am__dry = yes; \
-  }
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
 pkgdatadir = $(datadir)/@PACKAGE@
 pkgincludedir = $(includedir)/@PACKAGE@
 pkglibdir = $(libdir)/@PACKAGE@
@@ -60,7 +88,10 @@ host_triplet = @host@
 @NO_READOSM_FALSE@	spatialite_osm_filter$(EXEEXT) \
 @NO_READOSM_FALSE@	spatialite_gml$(EXEEXT) \
 @NO_READOSM_FALSE@	spatialite_convert$(EXEEXT) \
- at NO_READOSM_FALSE@	spatialite_dxf$(EXEEXT)
+ at NO_READOSM_FALSE@	spatialite_dxf$(EXEEXT) \
+ at NO_READOSM_FALSE@	spatialite_xml_load$(EXEEXT) \
+ at NO_READOSM_FALSE@	spatialite_xml_collapse$(EXEEXT) \
+ at NO_READOSM_FALSE@	spatialite_xml_print$(EXEEXT)
 @NO_READOSM_TRUE at bin_PROGRAMS = spatialite$(EXEEXT) \
 @NO_READOSM_TRUE@	spatialite_tool$(EXEEXT) \
 @NO_READOSM_TRUE@	spatialite_network$(EXEEXT) \
@@ -68,12 +99,16 @@ host_triplet = @host@
 @NO_READOSM_TRUE@	spatialite_osm_filter$(EXEEXT) \
 @NO_READOSM_TRUE@	spatialite_gml$(EXEEXT) \
 @NO_READOSM_TRUE@	spatialite_convert$(EXEEXT) \
- at NO_READOSM_TRUE@	spatialite_dxf$(EXEEXT)
+ at NO_READOSM_TRUE@	spatialite_dxf$(EXEEXT) \
+ at NO_READOSM_TRUE@	spatialite_xml_load$(EXEEXT) \
+ at NO_READOSM_TRUE@	spatialite_xml_collapse$(EXEEXT) \
+ at NO_READOSM_TRUE@	spatialite_xml_print$(EXEEXT)
 subdir = .
-DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
-	$(srcdir)/Makefile.in $(srcdir)/config.h.in \
-	$(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \
-	config.guess config.sub depcomp install-sh ltmain.sh missing
+DIST_COMMON = INSTALL NEWS README AUTHORS ChangeLog \
+	$(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+	$(top_srcdir)/configure $(am__configure_deps) \
+	$(srcdir)/config.h.in depcomp COPYING config.guess config.sub \
+	install-sh missing ltmain.sh
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
 	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
@@ -93,6 +128,10 @@ am_exif_loader_OBJECTS = exif_loader.$(OBJEXT)
 exif_loader_OBJECTS = $(am_exif_loader_OBJECTS)
 exif_loader_LDADD = $(LDADD)
 exif_loader_DEPENDENCIES =
+AM_V_lt = $(am__v_lt_ at AM_V@)
+am__v_lt_ = $(am__v_lt_ at AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 = 
 am_shp_doctor_OBJECTS = shp_doctor.$(OBJEXT)
 shp_doctor_OBJECTS = $(am_shp_doctor_OBJECTS)
 shp_doctor_LDADD = $(LDADD)
@@ -138,25 +177,59 @@ am_spatialite_tool_OBJECTS = spatialite_tool.$(OBJEXT)
 spatialite_tool_OBJECTS = $(am_spatialite_tool_OBJECTS)
 spatialite_tool_LDADD = $(LDADD)
 spatialite_tool_DEPENDENCIES =
+am_spatialite_xml_collapse_OBJECTS =  \
+	spatialite_xml_collapse.$(OBJEXT)
+spatialite_xml_collapse_OBJECTS =  \
+	$(am_spatialite_xml_collapse_OBJECTS)
+spatialite_xml_collapse_DEPENDENCIES =
+am_spatialite_xml_load_OBJECTS = spatialite_xml_load.$(OBJEXT)
+spatialite_xml_load_OBJECTS = $(am_spatialite_xml_load_OBJECTS)
+spatialite_xml_load_DEPENDENCIES =
+am_spatialite_xml_print_OBJECTS = spatialite_xml_print.$(OBJEXT)
+spatialite_xml_print_OBJECTS = $(am_spatialite_xml_print_OBJECTS)
+spatialite_xml_print_LDADD = $(LDADD)
+spatialite_xml_print_DEPENDENCIES =
+AM_V_P = $(am__v_P_ at AM_V@)
+am__v_P_ = $(am__v_P_ at AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_ at AM_V@)
+am__v_GEN_ = $(am__v_GEN_ at AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_ at AM_V@)
+am__v_at_ = $(am__v_at_ at AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
 DEFAULT_INCLUDES = -I. at am__isrc@
 depcomp = $(SHELL) $(top_srcdir)/depcomp
 am__depfiles_maybe = depfiles
 am__mv = mv -f
 COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
 	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
-	--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
-	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_ at AM_V@)
+am__v_CC_ = $(am__v_CC_ at AM_DEFAULT_V@)
+am__v_CC_0 = @echo "  CC      " $@;
+am__v_CC_1 = 
 CCLD = $(CC)
-LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
-	--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
-	$(LDFLAGS) -o $@
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_ at AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_ at AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo "  CCLD    " $@;
+am__v_CCLD_1 = 
 SOURCES = $(exif_loader_SOURCES) $(shp_doctor_SOURCES) \
 	$(spatialite_SOURCES) spatialite_convert.c spatialite_dxf.c \
 	$(spatialite_gml_SOURCES) $(spatialite_network_SOURCES) \
 	$(spatialite_osm_filter_SOURCES) $(spatialite_osm_map_SOURCES) \
 	$(spatialite_osm_net_SOURCES) $(spatialite_osm_raw_SOURCES) \
-	$(spatialite_tool_SOURCES)
+	$(spatialite_tool_SOURCES) $(spatialite_xml_collapse_SOURCES) \
+	$(spatialite_xml_load_SOURCES) $(spatialite_xml_print_SOURCES)
 DIST_SOURCES = $(exif_loader_SOURCES) $(shp_doctor_SOURCES) \
 	$(spatialite_SOURCES) spatialite_convert.c spatialite_dxf.c \
 	$(spatialite_gml_SOURCES) $(spatialite_network_SOURCES) \
@@ -164,12 +237,31 @@ DIST_SOURCES = $(exif_loader_SOURCES) $(shp_doctor_SOURCES) \
 	$(am__spatialite_osm_map_SOURCES_DIST) \
 	$(am__spatialite_osm_net_SOURCES_DIST) \
 	$(am__spatialite_osm_raw_SOURCES_DIST) \
-	$(spatialite_tool_SOURCES)
+	$(spatialite_tool_SOURCES) $(spatialite_xml_collapse_SOURCES) \
+	$(spatialite_xml_load_SOURCES) $(spatialite_xml_print_SOURCES)
 am__can_run_installinfo = \
   case $$AM_UPDATE_INFO_DIR in \
     n|no|NO) false;; \
     *) (install-info --version) >/dev/null 2>&1;; \
   esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \
+	$(LISP)config.h.in
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
 ETAGS = etags
 CTAGS = ctags
 CSCOPE = cscope
@@ -193,6 +285,7 @@ am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
 distcleancheck_listfiles = find . -type f -print
 ACLOCAL = @ACLOCAL@
 AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
 AR = @AR@
 AS = @AS@
 AUTOCONF = @AUTOCONF@
@@ -325,12 +418,15 @@ top_build_prefix = @top_build_prefix@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 ACLOCAL_AMFLAGS = -I m4
-INCLUDES = @CFLAGS@ -I$(top_srcdir)
+AM_CPPFLAGS = @CFLAGS@ -I$(top_srcdir)
 spatialite_SOURCES = shell.c
 spatialite_tool_SOURCES = spatialite_tool.c
 spatialite_network_SOURCES = spatialite_network.c
 shp_doctor_SOURCES = shp_doctor.c
 exif_loader_SOURCES = exif_loader.c
+spatialite_xml_load_SOURCES = spatialite_xml_load.c
+spatialite_xml_collapse_SOURCES = spatialite_xml_collapse.c
+spatialite_xml_print_SOURCES = spatialite_xml_print.c 
 @NO_READOSM_FALSE at spatialite_osm_net_SOURCES = spatialite_osm_net.c
 @NO_READOSM_FALSE at spatialite_osm_map_SOURCES = spatialite_osm_map.c
 @NO_READOSM_FALSE at spatialite_osm_raw_SOURCES = spatialite_osm_raw.c
@@ -353,6 +449,11 @@ spatialite_LDADD = @LIBSPATIALITE_LIBS@ \
 	@LIBFREEXL_LIBS@ \
 	@READLINE_LIBS@
 
+spatialite_xml_load_LDADD = @LIBSPATIALITE_LIBS@ \
+	-lexpat
+
+spatialite_xml_collapse_LDADD = @LIBSPATIALITE_LIBS@
+spatialite_xml_print_LADD = @LIBSPATIALIATE_LIBS@
 LDADD = @LIBSPATIALITE_LIBS@ \
 	@LIBFREEXL_LIBS@
 
@@ -426,10 +527,12 @@ install-binPROGRAMS: $(bin_PROGRAMS)
 	fi; \
 	for p in $$list; do echo "$$p $$p"; done | \
 	sed 's/$(EXEEXT)$$//' | \
-	while read p p1; do if test -f $$p || test -f $$p1; \
-	  then echo "$$p"; echo "$$p"; else :; fi; \
+	while read p p1; do if test -f $$p \
+	 || test -f $$p1 \
+	  ; then echo "$$p"; echo "$$p"; else :; fi; \
 	done | \
-	sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
+	sed -e 'p;s,.*/,,;n;h' \
+	    -e 's|.*|.|' \
 	    -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
 	sed 'N;N;N;s,\n, ,g' | \
 	$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
@@ -450,7 +553,8 @@ uninstall-binPROGRAMS:
 	@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
 	files=`for p in $$list; do echo "$$p"; done | \
 	  sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
-	      -e 's/$$/$(EXEEXT)/' `; \
+	      -e 's/$$/$(EXEEXT)/' \
+	`; \
 	test -n "$$list" || exit 0; \
 	echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
 	cd "$(DESTDIR)$(bindir)" && rm -f $$files
@@ -463,42 +567,66 @@ clean-binPROGRAMS:
 	list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
 	echo " rm -f" $$list; \
 	rm -f $$list
+
 exif_loader$(EXEEXT): $(exif_loader_OBJECTS) $(exif_loader_DEPENDENCIES) $(EXTRA_exif_loader_DEPENDENCIES) 
 	@rm -f exif_loader$(EXEEXT)
-	$(LINK) $(exif_loader_OBJECTS) $(exif_loader_LDADD) $(LIBS)
+	$(AM_V_CCLD)$(LINK) $(exif_loader_OBJECTS) $(exif_loader_LDADD) $(LIBS)
+
 shp_doctor$(EXEEXT): $(shp_doctor_OBJECTS) $(shp_doctor_DEPENDENCIES) $(EXTRA_shp_doctor_DEPENDENCIES) 
 	@rm -f shp_doctor$(EXEEXT)
-	$(LINK) $(shp_doctor_OBJECTS) $(shp_doctor_LDADD) $(LIBS)
+	$(AM_V_CCLD)$(LINK) $(shp_doctor_OBJECTS) $(shp_doctor_LDADD) $(LIBS)
+
 spatialite$(EXEEXT): $(spatialite_OBJECTS) $(spatialite_DEPENDENCIES) $(EXTRA_spatialite_DEPENDENCIES) 
 	@rm -f spatialite$(EXEEXT)
-	$(LINK) $(spatialite_OBJECTS) $(spatialite_LDADD) $(LIBS)
+	$(AM_V_CCLD)$(LINK) $(spatialite_OBJECTS) $(spatialite_LDADD) $(LIBS)
+
 spatialite_convert$(EXEEXT): $(spatialite_convert_OBJECTS) $(spatialite_convert_DEPENDENCIES) $(EXTRA_spatialite_convert_DEPENDENCIES) 
 	@rm -f spatialite_convert$(EXEEXT)
-	$(LINK) $(spatialite_convert_OBJECTS) $(spatialite_convert_LDADD) $(LIBS)
+	$(AM_V_CCLD)$(LINK) $(spatialite_convert_OBJECTS) $(spatialite_convert_LDADD) $(LIBS)
+
 spatialite_dxf$(EXEEXT): $(spatialite_dxf_OBJECTS) $(spatialite_dxf_DEPENDENCIES) $(EXTRA_spatialite_dxf_DEPENDENCIES) 
 	@rm -f spatialite_dxf$(EXEEXT)
-	$(LINK) $(spatialite_dxf_OBJECTS) $(spatialite_dxf_LDADD) $(LIBS)
+	$(AM_V_CCLD)$(LINK) $(spatialite_dxf_OBJECTS) $(spatialite_dxf_LDADD) $(LIBS)
+
 spatialite_gml$(EXEEXT): $(spatialite_gml_OBJECTS) $(spatialite_gml_DEPENDENCIES) $(EXTRA_spatialite_gml_DEPENDENCIES) 
 	@rm -f spatialite_gml$(EXEEXT)
-	$(LINK) $(spatialite_gml_OBJECTS) $(spatialite_gml_LDADD) $(LIBS)
+	$(AM_V_CCLD)$(LINK) $(spatialite_gml_OBJECTS) $(spatialite_gml_LDADD) $(LIBS)
+
 spatialite_network$(EXEEXT): $(spatialite_network_OBJECTS) $(spatialite_network_DEPENDENCIES) $(EXTRA_spatialite_network_DEPENDENCIES) 
 	@rm -f spatialite_network$(EXEEXT)
-	$(LINK) $(spatialite_network_OBJECTS) $(spatialite_network_LDADD) $(LIBS)
+	$(AM_V_CCLD)$(LINK) $(spatialite_network_OBJECTS) $(spatialite_network_LDADD) $(LIBS)
+
 spatialite_osm_filter$(EXEEXT): $(spatialite_osm_filter_OBJECTS) $(spatialite_osm_filter_DEPENDENCIES) $(EXTRA_spatialite_osm_filter_DEPENDENCIES) 
 	@rm -f spatialite_osm_filter$(EXEEXT)
-	$(LINK) $(spatialite_osm_filter_OBJECTS) $(spatialite_osm_filter_LDADD) $(LIBS)
+	$(AM_V_CCLD)$(LINK) $(spatialite_osm_filter_OBJECTS) $(spatialite_osm_filter_LDADD) $(LIBS)
+
 spatialite_osm_map$(EXEEXT): $(spatialite_osm_map_OBJECTS) $(spatialite_osm_map_DEPENDENCIES) $(EXTRA_spatialite_osm_map_DEPENDENCIES) 
 	@rm -f spatialite_osm_map$(EXEEXT)
-	$(LINK) $(spatialite_osm_map_OBJECTS) $(spatialite_osm_map_LDADD) $(LIBS)
+	$(AM_V_CCLD)$(LINK) $(spatialite_osm_map_OBJECTS) $(spatialite_osm_map_LDADD) $(LIBS)
+
 spatialite_osm_net$(EXEEXT): $(spatialite_osm_net_OBJECTS) $(spatialite_osm_net_DEPENDENCIES) $(EXTRA_spatialite_osm_net_DEPENDENCIES) 
 	@rm -f spatialite_osm_net$(EXEEXT)
-	$(LINK) $(spatialite_osm_net_OBJECTS) $(spatialite_osm_net_LDADD) $(LIBS)
+	$(AM_V_CCLD)$(LINK) $(spatialite_osm_net_OBJECTS) $(spatialite_osm_net_LDADD) $(LIBS)
+
 spatialite_osm_raw$(EXEEXT): $(spatialite_osm_raw_OBJECTS) $(spatialite_osm_raw_DEPENDENCIES) $(EXTRA_spatialite_osm_raw_DEPENDENCIES) 
 	@rm -f spatialite_osm_raw$(EXEEXT)
-	$(LINK) $(spatialite_osm_raw_OBJECTS) $(spatialite_osm_raw_LDADD) $(LIBS)
+	$(AM_V_CCLD)$(LINK) $(spatialite_osm_raw_OBJECTS) $(spatialite_osm_raw_LDADD) $(LIBS)
+
 spatialite_tool$(EXEEXT): $(spatialite_tool_OBJECTS) $(spatialite_tool_DEPENDENCIES) $(EXTRA_spatialite_tool_DEPENDENCIES) 
 	@rm -f spatialite_tool$(EXEEXT)
-	$(LINK) $(spatialite_tool_OBJECTS) $(spatialite_tool_LDADD) $(LIBS)
+	$(AM_V_CCLD)$(LINK) $(spatialite_tool_OBJECTS) $(spatialite_tool_LDADD) $(LIBS)
+
+spatialite_xml_collapse$(EXEEXT): $(spatialite_xml_collapse_OBJECTS) $(spatialite_xml_collapse_DEPENDENCIES) $(EXTRA_spatialite_xml_collapse_DEPENDENCIES) 
+	@rm -f spatialite_xml_collapse$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(spatialite_xml_collapse_OBJECTS) $(spatialite_xml_collapse_LDADD) $(LIBS)
+
+spatialite_xml_load$(EXEEXT): $(spatialite_xml_load_OBJECTS) $(spatialite_xml_load_DEPENDENCIES) $(EXTRA_spatialite_xml_load_DEPENDENCIES) 
+	@rm -f spatialite_xml_load$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(spatialite_xml_load_OBJECTS) $(spatialite_xml_load_LDADD) $(LIBS)
+
+spatialite_xml_print$(EXEEXT): $(spatialite_xml_print_OBJECTS) $(spatialite_xml_print_DEPENDENCIES) $(EXTRA_spatialite_xml_print_DEPENDENCIES) 
+	@rm -f spatialite_xml_print$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(spatialite_xml_print_OBJECTS) $(spatialite_xml_print_LDADD) $(LIBS)
 
 mostlyclean-compile:
 	-rm -f *.$(OBJEXT)
@@ -518,27 +646,30 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/spatialite_osm_net.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/spatialite_osm_raw.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/spatialite_tool.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/spatialite_xml_collapse.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/spatialite_xml_load.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/spatialite_xml_print.Po at am__quote@
 
 .c.o:
- at am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
- at am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(COMPILE) -c $<
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(COMPILE) -c $<
 
 .c.obj:
- at am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
- at am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(COMPILE) -c `$(CYGPATH_W) '$<'`
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
 
 .c.lo:
- at am__fastdepCC_TRUE@	$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
- at am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(LTCOMPILE) -c -o $@ $<
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LTCOMPILE) -c -o $@ $<
 
 mostlyclean-libtool:
 	-rm -f *.lo
@@ -549,26 +680,15 @@ clean-libtool:
 distclean-libtool:
 	-rm -f libtool config.lt
 
-ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
-	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
-	unique=`for i in $$list; do \
-	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-	  done | \
-	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
-	      END { if (nonempty) { for (i in files) print i; }; }'`; \
-	mkid -fID $$unique
-tags: TAGS
-
-TAGS:  $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
-		$(TAGS_FILES) $(LISP)
+ID: $(am__tagged_files)
+	$(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
 	set x; \
 	here=`pwd`; \
-	list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
-	unique=`for i in $$list; do \
-	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-	  done | \
-	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
-	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	$(am__define_uniq_tagged_files); \
 	shift; \
 	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
 	  test -n "$$unique" || unique=$$empty_fix; \
@@ -580,15 +700,11 @@ TAGS:  $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
 	      $$unique; \
 	  fi; \
 	fi
-ctags: CTAGS
-CTAGS:  $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
-		$(TAGS_FILES) $(LISP)
-	list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
-	unique=`for i in $$list; do \
-	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-	  done | \
-	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
-	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	$(am__define_uniq_tagged_files); \
 	test -z "$(CTAGS_ARGS)$$unique" \
 	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
 	     $$unique
@@ -597,18 +713,16 @@ GTAGS:
 	here=`$(am__cd) $(top_builddir) && pwd` \
 	  && $(am__cd) $(top_srcdir) \
 	  && gtags -i $(GTAGS_ARGS) "$$here"
-
 cscope: cscope.files
 	test ! -s cscope.files \
 	  || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS)
-
 clean-cscope:
 	-rm -f cscope.files
+cscope.files: clean-cscope cscopelist
+cscopelist: cscopelist-am
 
-cscope.files: clean-cscope  cscopelist
-
-cscopelist:  $(HEADERS) $(SOURCES) $(LISP)
-	list='$(SOURCES) $(HEADERS) $(LISP)'; \
+cscopelist-am: $(am__tagged_files)
+	list='$(am__tagged_files)'; \
 	case "$(srcdir)" in \
 	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
 	  *) sdir=$(subdir)/$(srcdir) ;; \
@@ -716,9 +830,9 @@ distcheck: dist
 	*.zip*) \
 	  unzip $(distdir).zip ;;\
 	esac
-	chmod -R a-w $(distdir); chmod u+w $(distdir)
-	mkdir $(distdir)/_build
-	mkdir $(distdir)/_inst
+	chmod -R a-w $(distdir)
+	chmod u+w $(distdir)
+	mkdir $(distdir)/_build $(distdir)/_inst
 	chmod a-w $(distdir)
 	test -d $(distdir)/_build || exit 0; \
 	dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
@@ -892,14 +1006,14 @@ uninstall-am: uninstall-binPROGRAMS
 
 .MAKE: all install-am install-strip
 
-.PHONY: CTAGS GTAGS all all-am am--refresh check check-am clean \
+.PHONY: CTAGS GTAGS TAGS all all-am am--refresh check check-am clean \
 	clean-binPROGRAMS clean-cscope clean-generic clean-libtool \
-	cscope cscopelist ctags dist dist-all dist-bzip2 dist-gzip \
-	dist-lzip dist-shar dist-tarZ dist-xz dist-zip distcheck \
-	distclean distclean-compile distclean-generic distclean-hdr \
-	distclean-libtool distclean-tags distcleancheck distdir \
-	distuninstallcheck dvi dvi-am html html-am info info-am \
-	install install-am install-binPROGRAMS install-data \
+	cscope cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \
+	dist-gzip dist-lzip dist-shar dist-tarZ dist-xz dist-zip \
+	distcheck distclean distclean-compile distclean-generic \
+	distclean-hdr distclean-libtool distclean-tags distcleancheck \
+	distdir distuninstallcheck dvi dvi-am html html-am info \
+	info-am install install-am install-binPROGRAMS install-data \
 	install-data-am install-dvi install-dvi-am install-exec \
 	install-exec-am install-html install-html-am install-info \
 	install-info-am install-man install-pdf install-pdf-am \
@@ -907,7 +1021,7 @@ uninstall-am: uninstall-binPROGRAMS
 	installcheck-am installdirs maintainer-clean \
 	maintainer-clean-generic mostlyclean mostlyclean-compile \
 	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
-	tags uninstall uninstall-am uninstall-binPROGRAMS
+	tags tags-am uninstall uninstall-am uninstall-binPROGRAMS
 
 
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/aclocal.m4 b/aclocal.m4
index 5e48e24..f209970 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -1,6 +1,6 @@
-# generated automatically by aclocal 1.12.2 -*- Autoconf -*-
+# generated automatically by aclocal 1.13.4 -*- Autoconf -*-
 
-# Copyright (C) 1996-2012 Free Software Foundation, Inc.
+# Copyright (C) 1996-2013 Free Software Foundation, Inc.
 
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -11,6 +11,7 @@
 # even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 # PARTICULAR PURPOSE.
 
+m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
 m4_ifndef([AC_AUTOCONF_VERSION],
   [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
 m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],,
@@ -219,24 +220,37 @@ m4_popdef([pkg_default])
 m4_popdef([pkg_description])
 ]) dnl PKG_NOARCH_INSTALLDIR
 
-# Copyright (C) 2002-2012 Free Software Foundation, Inc.
+
+# PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
+# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+# -------------------------------------------
+# Retrieves the value of the pkg-config variable for the given module.
+AC_DEFUN([PKG_CHECK_VAR],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
+
+_PKG_CONFIG([$1], [variable="][$3]["], [$2])
+AS_VAR_COPY([$1], [pkg_cv_][$1])
+
+AS_VAR_IF([$1], [""], [$5], [$4])dnl
+])# PKG_CHECK_VAR
+
+# Copyright (C) 2002-2013 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-# serial 8
-
 # AM_AUTOMAKE_VERSION(VERSION)
 # ----------------------------
 # Automake X.Y traces this macro to ensure aclocal.m4 has been
 # generated from the m4 files accompanying Automake X.Y.
 # (This private macro should not be called outside this file.)
 AC_DEFUN([AM_AUTOMAKE_VERSION],
-[am__api_version='1.12'
+[am__api_version='1.13'
 dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
 dnl require some minimum version.  Point them to the right macro.
-m4_if([$1], [1.12.2], [],
+m4_if([$1], [1.13.4], [],
       [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
 ])
 
@@ -252,21 +266,19 @@ m4_define([_AM_AUTOCONF_VERSION], [])
 # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
 # This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
 AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
-[AM_AUTOMAKE_VERSION([1.12.2])dnl
+[AM_AUTOMAKE_VERSION([1.13.4])dnl
 m4_ifndef([AC_AUTOCONF_VERSION],
   [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
 _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
 
 # AM_AUX_DIR_EXPAND                                         -*- Autoconf -*-
 
-# Copyright (C) 2001-2012 Free Software Foundation, Inc.
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-# serial 2
-
 # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
 # $ac_aux_dir to '$srcdir/foo'.  In other projects, it is set to
 # '$srcdir', '$srcdir/..', or '$srcdir/../..'.
@@ -314,14 +326,12 @@ am_aux_dir=`cd $ac_aux_dir && pwd`
 
 # AM_CONDITIONAL                                            -*- Autoconf -*-
 
-# Copyright (C) 1997-2012 Free Software Foundation, Inc.
+# Copyright (C) 1997-2013 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-# serial 10
-
 # AM_CONDITIONAL(NAME, SHELL-CONDITION)
 # -------------------------------------
 # Define a conditional.
@@ -347,13 +357,12 @@ AC_CONFIG_COMMANDS_PRE(
 Usually this means the macro was only invoked conditionally.]])
 fi])])
 
-# Copyright (C) 1999-2012 Free Software Foundation, Inc.
+# Copyright (C) 1999-2013 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-# serial 17
 
 # There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be
 # written in clear, in which case automake, when reading aclocal.m4,
@@ -539,19 +548,18 @@ _AM_SUBST_NOTMAKE([am__nodep])dnl
 
 # Generate code to set up dependency tracking.              -*- Autoconf -*-
 
-# Copyright (C) 1999-2012 Free Software Foundation, Inc.
+# Copyright (C) 1999-2013 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-# serial 6
 
 # _AM_OUTPUT_DEPENDENCY_COMMANDS
 # ------------------------------
 AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
 [{
-  # Autoconf 2.62 quotes --file arguments for eval, but not when files
+  # Older Autoconf quotes --file arguments for eval, but not when files
   # are listed without --file.  Let's play safe and only enable the eval
   # if we detect the quoting.
   case $CONFIG_FILES in
@@ -580,7 +588,7 @@ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
     DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
     test -z "$DEPDIR" && continue
     am__include=`sed -n 's/^am__include = //p' < "$mf"`
-    test -z "am__include" && continue
+    test -z "$am__include" && continue
     am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
     # Find all dependency output files, they are included files with
     # $(DEPDIR) in their names.  We invoke sed twice because it is the
@@ -614,27 +622,14 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
      [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
 ])
 
-# Copyright (C) 1996-2012 Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# serial 8
-
-# AM_CONFIG_HEADER is obsolete.  It has been replaced by AC_CONFIG_HEADERS.
-AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)])
-
 # Do all the work for Automake.                             -*- Autoconf -*-
 
-# Copyright (C) 1996-2012 Free Software Foundation, Inc.
+# Copyright (C) 1996-2013 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-# serial 19
-
 # This macro actually does too much.  Some checks are only needed if
 # your package does certain things.  But this isn't really a big deal.
 
@@ -650,7 +645,7 @@ AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)])
 # arguments mandatory, and then we can depend on a new Autoconf
 # release and drop the old call support.
 AC_DEFUN([AM_INIT_AUTOMAKE],
-[AC_PREREQ([2.62])dnl
+[AC_PREREQ([2.65])dnl
 dnl Autoconf wants to disallow AM_ names.  We explicitly allow
 dnl the ones we care about.
 m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
@@ -680,8 +675,7 @@ AC_SUBST([CYGPATH_W])
 dnl Distinguish between old-style and new-style calls.
 m4_ifval([$2],
 [AC_DIAGNOSE([obsolete],
-[$0: two- and three-arguments forms are deprecated.  For more info, see:
-http://www.gnu.org/software/automake/manual/automake.html#Modernize-AM_INIT_AUTOMAKE-invocation])
+             [$0: two- and three-arguments forms are deprecated.])
 m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
  AC_SUBST([PACKAGE], [$1])dnl
  AC_SUBST([VERSION], [$2])],
@@ -735,18 +729,15 @@ AC_PROVIDE_IFELSE([AC_PROG_OBJC],
 		  [_AM_DEPENDENCIES([OBJC])],
 		  [m4_define([AC_PROG_OBJC],
 			     m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl
-dnl Support for Objective C++ was only introduced in Autoconf 2.65,
-dnl but we still cater to Autoconf 2.62.
-m4_ifdef([AC_PROG_OBJCXX],
-[AC_PROVIDE_IFELSE([AC_PROG_OBJCXX],
+AC_PROVIDE_IFELSE([AC_PROG_OBJCXX],
 		  [_AM_DEPENDENCIES([OBJCXX])],
 		  [m4_define([AC_PROG_OBJCXX],
-			     m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])])dnl
+			     m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl
 ])
-_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl
-dnl The 'parallel-tests' driver may need to know about EXEEXT, so add the
-dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen.  This macro
-dnl is hooked onto _AC_COMPILER_EXEEXT early, see below.
+AC_REQUIRE([AM_SILENT_RULES])dnl
+dnl The testsuite driver may need to know about EXEEXT, so add the
+dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen.  This
+dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below.
 AC_CONFIG_COMMANDS_PRE(dnl
 [m4_provide_if([_AM_COMPILER_EXEEXT],
   [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
@@ -780,14 +771,12 @@ for _am_header in $config_headers :; do
 done
 echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
 
-# Copyright (C) 2001-2012 Free Software Foundation, Inc.
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-# serial 8
-
 # AM_PROG_INSTALL_SH
 # ------------------
 # Define $install_sh.
@@ -803,14 +792,12 @@ if test x"${install_sh}" != xset; then
 fi
 AC_SUBST([install_sh])])
 
-# Copyright (C) 2003-2012 Free Software Foundation, Inc.
+# Copyright (C) 2003-2013 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-# serial 2
-
 # Check whether the underlying file-system supports filenames
 # with a leading dot.  For instance MS-DOS doesn't.
 AC_DEFUN([AM_SET_LEADING_DOT],
@@ -827,14 +814,12 @@ AC_SUBST([am__leading_dot])])
 # Add --enable-maintainer-mode option to configure.         -*- Autoconf -*-
 # From Jim Meyering
 
-# Copyright (C) 1996-2012 Free Software Foundation, Inc.
+# Copyright (C) 1996-2013 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-# serial 7
-
 # AM_MAINTAINER_MODE([DEFAULT-MODE])
 # ----------------------------------
 # Control maintainer-specific portions of Makefiles.
@@ -862,18 +847,14 @@ AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
 ]
 )
 
-AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE])
-
 # Check to see how 'make' treats includes.	            -*- Autoconf -*-
 
-# Copyright (C) 2001-2012 Free Software Foundation, Inc.
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-# serial 5
-
 # AM_MAKE_INCLUDE()
 # -----------------
 # Check to see how make treats includes.
@@ -918,14 +899,12 @@ rm -f confinc confmf
 
 # Fake the existence of programs that GNU maintainers use.  -*- Autoconf -*-
 
-# Copyright (C) 1997-2012 Free Software Foundation, Inc.
+# Copyright (C) 1997-2013 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-# serial 7
-
 # AM_MISSING_PROG(NAME, PROGRAM)
 # ------------------------------
 AC_DEFUN([AM_MISSING_PROG],
@@ -933,11 +912,10 @@ AC_DEFUN([AM_MISSING_PROG],
 $1=${$1-"${am_missing_run}$2"}
 AC_SUBST($1)])
 
-
 # AM_MISSING_HAS_RUN
 # ------------------
-# Define MISSING if not defined so far and test if it supports --run.
-# If it does, set am_missing_run to use it, otherwise, to nothing.
+# Define MISSING if not defined so far and test if it is modern enough.
+# If it is, set am_missing_run to use it, otherwise, to nothing.
 AC_DEFUN([AM_MISSING_HAS_RUN],
 [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
 AC_REQUIRE_AUX_FILE([missing])dnl
@@ -950,24 +928,51 @@ if test x"${MISSING+set}" != xset; then
   esac
 fi
 # Use eval to expand $SHELL
-if eval "$MISSING --run true"; then
-  am_missing_run="$MISSING --run "
+if eval "$MISSING --is-lightweight"; then
+  am_missing_run="$MISSING "
 else
   am_missing_run=
   AC_MSG_WARN(['missing' script is too old or missing])
 fi
 ])
 
+#  -*- Autoconf -*-
+# Obsolete and "removed" macros, that must however still report explicit
+# error messages when used, to smooth transition.
+#
+# Copyright (C) 1996-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([AM_CONFIG_HEADER],
+[AC_DIAGNOSE([obsolete],
+['$0': this macro is obsolete.
+You should use the 'AC][_CONFIG_HEADERS' macro instead.])dnl
+AC_CONFIG_HEADERS($@)])
+
+AC_DEFUN([AM_PROG_CC_STDC],
+[AC_PROG_CC
+am_cv_prog_cc_stdc=$ac_cv_prog_cc_stdc
+AC_DIAGNOSE([obsolete],
+['$0': this macro is obsolete.
+You should simply use the 'AC][_PROG_CC' macro instead.
+Also, your code should no longer depend upon 'am_cv_prog_cc_stdc',
+but upon 'ac_cv_prog_cc_stdc'.])])
+
+AC_DEFUN([AM_C_PROTOTYPES],
+         [AC_FATAL([automatic de-ANSI-fication support has been removed])])
+AU_DEFUN([fp_C_PROTOTYPES], [AM_C_PROTOTYPES])
+
 # Helper functions for option handling.                     -*- Autoconf -*-
 
-# Copyright (C) 2001-2012 Free Software Foundation, Inc.
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-# serial 6
-
 # _AM_MANGLE_OPTION(NAME)
 # -----------------------
 AC_DEFUN([_AM_MANGLE_OPTION],
@@ -993,14 +998,12 @@ AC_DEFUN([_AM_IF_OPTION],
 
 # Check to make sure that the build environment is sane.    -*- Autoconf -*-
 
-# Copyright (C) 1996-2012 Free Software Foundation, Inc.
+# Copyright (C) 1996-2013 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-# serial 9
-
 # AM_SANITY_CHECK
 # ---------------
 AC_DEFUN([AM_SANITY_CHECK],
@@ -1076,13 +1079,71 @@ AC_CONFIG_COMMANDS_PRE(
 rm -f conftest.file
 ])
 
-# Copyright (C) 2001-2012 Free Software Foundation, Inc.
+# Copyright (C) 2009-2013 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-# serial 2
+# AM_SILENT_RULES([DEFAULT])
+# --------------------------
+# Enable less verbose build rules; with the default set to DEFAULT
+# ("yes" being less verbose, "no" or empty being verbose).
+AC_DEFUN([AM_SILENT_RULES],
+[AC_ARG_ENABLE([silent-rules], [dnl
+AS_HELP_STRING(
+  [--enable-silent-rules],
+  [less verbose build output (undo: "make V=1")])
+AS_HELP_STRING(
+  [--disable-silent-rules],
+  [verbose build output (undo: "make V=0")])dnl
+])
+case $enable_silent_rules in @%:@ (((
+  yes) AM_DEFAULT_VERBOSITY=0;;
+   no) AM_DEFAULT_VERBOSITY=1;;
+    *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);;
+esac
+dnl
+dnl A few 'make' implementations (e.g., NonStop OS and NextStep)
+dnl do not support nested variable expansions.
+dnl See automake bug#9928 and bug#10237.
+am_make=${MAKE-make}
+AC_CACHE_CHECK([whether $am_make supports nested variables],
+   [am_cv_make_support_nested_variables],
+   [if AS_ECHO([['TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+	@$(TRUE)
+.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then
+  am_cv_make_support_nested_variables=yes
+else
+  am_cv_make_support_nested_variables=no
+fi])
+if test $am_cv_make_support_nested_variables = yes; then
+  dnl Using '$V' instead of '$(V)' breaks IRIX make.
+  AM_V='$(V)'
+  AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+else
+  AM_V=$AM_DEFAULT_VERBOSITY
+  AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
+fi
+AC_SUBST([AM_V])dnl
+AM_SUBST_NOTMAKE([AM_V])dnl
+AC_SUBST([AM_DEFAULT_V])dnl
+AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl
+AC_SUBST([AM_DEFAULT_VERBOSITY])dnl
+AM_BACKSLASH='\'
+AC_SUBST([AM_BACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
+])
+
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
 
 # AM_PROG_INSTALL_STRIP
 # ---------------------
@@ -1106,14 +1167,12 @@ fi
 INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
 AC_SUBST([INSTALL_STRIP_PROGRAM])])
 
-# Copyright (C) 2006-2012 Free Software Foundation, Inc.
+# Copyright (C) 2006-2013 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-# serial 3
-
 # _AM_SUBST_NOTMAKE(VARIABLE)
 # ---------------------------
 # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
@@ -1127,14 +1186,12 @@ AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
 
 # Check how to create a tarball.                            -*- Autoconf -*-
 
-# Copyright (C) 2004-2012 Free Software Foundation, Inc.
+# Copyright (C) 2004-2013 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-# serial 3
-
 # _AM_PROG_TAR(FORMAT)
 # --------------------
 # Check how to create a tarball in format FORMAT.
@@ -1148,76 +1205,114 @@ AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
 # Substitute a variable $(am__untar) that extract such
 # a tarball read from stdin.
 #     $(am__untar) < result.tar
+#
 AC_DEFUN([_AM_PROG_TAR],
 [# Always define AMTAR for backward compatibility.  Yes, it's still used
 # in the wild :-(  We should find a proper way to deprecate it ...
 AC_SUBST([AMTAR], ['$${TAR-tar}'])
-m4_if([$1], [v7],
-     [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'],
-     [m4_case([$1], [ustar],, [pax],,
-              [m4_fatal([Unknown tar format])])
-AC_MSG_CHECKING([how to create a $1 tar archive])
-# Loop over all known methods to create a tar archive until one works.
+
+# We'll loop over all known methods to create a tar archive until one works.
 _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
-_am_tools=${am_cv_prog_tar_$1-$_am_tools}
-# Do not fold the above two line into one, because Tru64 sh and
-# Solaris sh will not grok spaces in the rhs of '-'.
-for _am_tool in $_am_tools
-do
-  case $_am_tool in
-  gnutar)
-    for _am_tar in tar gnutar gtar;
-    do
-      AM_RUN_LOG([$_am_tar --version]) && break
-    done
-    am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
-    am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
-    am__untar="$_am_tar -xf -"
-    ;;
-  plaintar)
-    # Must skip GNU tar: if it does not support --format= it doesn't create
-    # ustar tarball either.
-    (tar --version) >/dev/null 2>&1 && continue
-    am__tar='tar chf - "$$tardir"'
-    am__tar_='tar chf - "$tardir"'
-    am__untar='tar xf -'
-    ;;
-  pax)
-    am__tar='pax -L -x $1 -w "$$tardir"'
-    am__tar_='pax -L -x $1 -w "$tardir"'
-    am__untar='pax -r'
-    ;;
-  cpio)
-    am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
-    am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
-    am__untar='cpio -i -H $1 -d'
-    ;;
-  none)
-    am__tar=false
-    am__tar_=false
-    am__untar=false
-    ;;
-  esac
 
-  # If the value was cached, stop now.  We just wanted to have am__tar
-  # and am__untar set.
-  test -n "${am_cv_prog_tar_$1}" && break
+m4_if([$1], [v7],
+  [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'],
+
+  [m4_case([$1],
+    [ustar],
+     [# The POSIX 1988 'ustar' format is defined with fixed-size fields.
+      # There is notably a 21 bits limit for the UID and the GID.  In fact,
+      # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343
+      # and bug#13588).
+      am_max_uid=2097151 # 2^21 - 1
+      am_max_gid=$am_max_uid
+      # The $UID and $GID variables are not portable, so we need to resort
+      # to the POSIX-mandated id(1) utility.  Errors in the 'id' calls
+      # below are definitely unexpected, so allow the users to see them
+      # (that is, avoid stderr redirection).
+      am_uid=`id -u || echo unknown`
+      am_gid=`id -g || echo unknown`
+      AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format])
+      if test $am_uid -le $am_max_uid; then
+         AC_MSG_RESULT([yes])
+      else
+         AC_MSG_RESULT([no])
+         _am_tools=none
+      fi
+      AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format])
+      if test $am_gid -le $am_max_gid; then
+         AC_MSG_RESULT([yes])
+      else
+        AC_MSG_RESULT([no])
+        _am_tools=none
+      fi],
+
+  [pax],
+    [],
+
+  [m4_fatal([Unknown tar format])])
+
+  AC_MSG_CHECKING([how to create a $1 tar archive])
+
+  # Go ahead even if we have the value already cached.  We do so because we
+  # need to set the values for the 'am__tar' and 'am__untar' variables.
+  _am_tools=${am_cv_prog_tar_$1-$_am_tools}
+
+  for _am_tool in $_am_tools; do
+    case $_am_tool in
+    gnutar)
+      for _am_tar in tar gnutar gtar; do
+        AM_RUN_LOG([$_am_tar --version]) && break
+      done
+      am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+      am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+      am__untar="$_am_tar -xf -"
+      ;;
+    plaintar)
+      # Must skip GNU tar: if it does not support --format= it doesn't create
+      # ustar tarball either.
+      (tar --version) >/dev/null 2>&1 && continue
+      am__tar='tar chf - "$$tardir"'
+      am__tar_='tar chf - "$tardir"'
+      am__untar='tar xf -'
+      ;;
+    pax)
+      am__tar='pax -L -x $1 -w "$$tardir"'
+      am__tar_='pax -L -x $1 -w "$tardir"'
+      am__untar='pax -r'
+      ;;
+    cpio)
+      am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+      am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+      am__untar='cpio -i -H $1 -d'
+      ;;
+    none)
+      am__tar=false
+      am__tar_=false
+      am__untar=false
+      ;;
+    esac
 
-  # tar/untar a dummy directory, and stop if the command works
-  rm -rf conftest.dir
-  mkdir conftest.dir
-  echo GrepMe > conftest.dir/file
-  AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+    # If the value was cached, stop now.  We just wanted to have am__tar
+    # and am__untar set.
+    test -n "${am_cv_prog_tar_$1}" && break
+
+    # tar/untar a dummy directory, and stop if the command works.
+    rm -rf conftest.dir
+    mkdir conftest.dir
+    echo GrepMe > conftest.dir/file
+    AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+    rm -rf conftest.dir
+    if test -s conftest.tar; then
+      AM_RUN_LOG([$am__untar <conftest.tar])
+      AM_RUN_LOG([cat conftest.dir/file])
+      grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+    fi
+  done
   rm -rf conftest.dir
-  if test -s conftest.tar; then
-    AM_RUN_LOG([$am__untar <conftest.tar])
-    grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
-  fi
-done
-rm -rf conftest.dir
 
-AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
-AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+  AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+  AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+
 AC_SUBST([am__tar])
 AC_SUBST([am__untar])
 ]) # _AM_PROG_TAR
diff --git a/configure b/configure
index ef375f5..65b1cd6 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for spatialite-tools 4.1.1.
+# Generated by GNU Autoconf 2.69 for spatialite-tools 4.2.0.
 #
 # Report bugs to <a.furieri at lqt.it>.
 #
@@ -590,8 +590,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='spatialite-tools'
 PACKAGE_TARNAME='spatialite-tools'
-PACKAGE_VERSION='4.1.1'
-PACKAGE_STRING='spatialite-tools 4.1.1'
+PACKAGE_VERSION='4.2.0'
+PACKAGE_STRING='spatialite-tools 4.2.0'
 PACKAGE_BUGREPORT='a.furieri at lqt.it'
 PACKAGE_URL=''
 
@@ -708,6 +708,10 @@ CC
 MAINT
 MAINTAINER_MODE_FALSE
 MAINTAINER_MODE_TRUE
+AM_BACKSLASH
+AM_DEFAULT_VERBOSITY
+AM_DEFAULT_V
+AM_V
 am__untar
 am__tar
 AMTAR
@@ -772,6 +776,7 @@ SHELL'
 ac_subst_files=''
 ac_user_opts='
 enable_option_checking
+enable_silent_rules
 enable_maintainer_mode
 enable_dependency_tracking
 enable_shared
@@ -1348,7 +1353,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures spatialite-tools 4.1.1 to adapt to many kinds of systems.
+\`configure' configures spatialite-tools 4.2.0 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1419,7 +1424,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of spatialite-tools 4.1.1:";;
+     short | recursive ) echo "Configuration of spatialite-tools 4.2.0:";;
    esac
   cat <<\_ACEOF
 
@@ -1427,6 +1432,8 @@ Optional Features:
   --disable-option-checking  ignore unrecognized --enable/--with options
   --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
   --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --enable-silent-rules   less verbose build output (undo: "make V=1")
+  --disable-silent-rules  verbose build output (undo: "make V=0")
   --enable-maintainer-mode
                           enable make rules and dependencies not useful (and
                           sometimes confusing) to the casual installer
@@ -1549,7 +1556,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-spatialite-tools configure 4.1.1
+spatialite-tools configure 4.2.0
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2139,7 +2146,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by spatialite-tools $as_me 4.1.1, which was
+It was created by spatialite-tools $as_me 4.2.0, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2495,7 +2502,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
 
-am__api_version='1.12'
+am__api_version='1.13'
 
 ac_aux_dir=
 for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
@@ -2708,8 +2715,8 @@ if test x"${MISSING+set}" != xset; then
   esac
 fi
 # Use eval to expand $SHELL
-if eval "$MISSING --run true"; then
-  am_missing_run="$MISSING --run "
+if eval "$MISSING --is-lightweight"; then
+  am_missing_run="$MISSING "
 else
   am_missing_run=
   { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5
@@ -2949,6 +2956,45 @@ else
 fi
 rmdir .tst 2>/dev/null
 
+# Check whether --enable-silent-rules was given.
+if test "${enable_silent_rules+set}" = set; then :
+  enableval=$enable_silent_rules;
+fi
+
+case $enable_silent_rules in # (((
+  yes) AM_DEFAULT_VERBOSITY=0;;
+   no) AM_DEFAULT_VERBOSITY=1;;
+    *) AM_DEFAULT_VERBOSITY=1;;
+esac
+am_make=${MAKE-make}
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5
+$as_echo_n "checking whether $am_make supports nested variables... " >&6; }
+if ${am_cv_make_support_nested_variables+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if $as_echo 'TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+	@$(TRUE)
+.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then
+  am_cv_make_support_nested_variables=yes
+else
+  am_cv_make_support_nested_variables=no
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5
+$as_echo "$am_cv_make_support_nested_variables" >&6; }
+if test $am_cv_make_support_nested_variables = yes; then
+    AM_V='$(V)'
+  AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+else
+  AM_V=$AM_DEFAULT_VERBOSITY
+  AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
+fi
+AM_BACKSLASH='\'
+
 if test "`cd $srcdir && pwd`" != "`pwd`"; then
   # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
   # is not polluted with repeated "-I."
@@ -2971,7 +3017,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='spatialite-tools'
- VERSION='4.1.1'
+ VERSION='4.2.0'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -3011,6 +3057,10 @@ mkdir_p='$(MKDIR_P)'
 # in the wild :-(  We should find a proper way to deprecate it ...
 AMTAR='$${TAR-tar}'
 
+
+# We'll loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar  pax cpio none'
+
 am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'
 
 
@@ -3018,6 +3068,7 @@ am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'
 
 
 
+
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5
 $as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; }
     # Check whether --enable-maintainer-mode was given.
@@ -18019,7 +18070,6 @@ DEFS=-DHAVE_CONFIG_H
 
 ac_libobjs=
 ac_ltlibobjs=
-U=
 for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
   # 1. Remove the extension, and $U if already installed.
   ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
@@ -18471,7 +18521,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by spatialite-tools $as_me 4.1.1, which was
+This file was extended by spatialite-tools $as_me 4.2.0, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -18537,7 +18587,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-spatialite-tools config.status 4.1.1
+spatialite-tools config.status 4.2.0
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
@@ -19645,7 +19695,7 @@ $as_echo "$as_me: executing $ac_file commands" >&6;}
 
   case $ac_file$ac_mode in
     "depfiles":C) test x"$AMDEP_TRUE" != x"" || {
-  # Autoconf 2.62 quotes --file arguments for eval, but not when files
+  # Older Autoconf quotes --file arguments for eval, but not when files
   # are listed without --file.  Let's play safe and only enable the eval
   # if we detect the quoting.
   case $CONFIG_FILES in
@@ -19696,7 +19746,7 @@ $as_echo X"$mf" |
     DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
     test -z "$DEPDIR" && continue
     am__include=`sed -n 's/^am__include = //p' < "$mf"`
-    test -z "am__include" && continue
+    test -z "$am__include" && continue
     am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
     # Find all dependency output files, they are included files with
     # $(DEPDIR) in their names.  We invoke sed twice because it is the
diff --git a/configure.ac b/configure.ac
index 19c2c05..e220aa4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@
 # Process this file with autoconf to produce a configure script.
 
 AC_PREREQ(2.61)
-AC_INIT(spatialite-tools, 4.1.1, a.furieri at lqt.it)
+AC_INIT(spatialite-tools, 4.2.0, a.furieri at lqt.it)
 AC_LANG(C)
 AC_CONFIG_MACRO_DIR([m4])
 
diff --git a/exif_loader.c b/exif_loader.c
index 1505b9c..25e2dd5 100644
--- a/exif_loader.c
+++ b/exif_loader.c
@@ -1617,5 +1617,6 @@ main (int argc, char *argv[])
 	fprintf (stderr,
 		 "\n\n***   %d EXIF photo%s successfully inserted into the DB\n",
 		 cnt, (cnt > 1) ? "s where" : " was");
+spatialite_shutdown();
     return 0;
 }
diff --git a/shell.c b/shell.c
index 810d4ea..6e70a81 100644
--- a/shell.c
+++ b/shell.c
@@ -119,6 +119,10 @@ extern int isatty(int);
 /* True if the timer is enabled */
 static int enableTimer = 0;
 
+/* sandro 2013-11-07 */
+void *splite_cache = NULL;
+/* end sandro 2013-11-07 */
+
 /* ctype macros that work with signed characters */
 #define IsSpace(X)  isspace((unsigned char)X)
 #define IsDigit(X)  isdigit((unsigned char)X)
@@ -259,6 +263,13 @@ static int sql_log_enabled = 1;
 static int bail_on_error = 0;
 
 /*
+** sandro 2013-08-30
+** If the following flag is set, no welcome message will be
+** printed at all.
+*/
+static int splite_silent = 0;
+
+/*
 ** Threat stdin as an interactive input if the following variable
 ** is true.  Otherwise, assume stdin is connected to a file or pipe.
 */
@@ -711,6 +722,40 @@ convert_to_utf8 (char *buf, int maxlen)
     free (utf8buf);
 }
 
+/* sandro 2013-11-17 */
+static void
+split_drop_name(const char *str, char **prefix, char **table)
+{
+    int len1;
+    int len2;
+    const char *pt = NULL;
+    const char *p = str;
+    *prefix = NULL;
+    *table = NULL;
+    while (*p != '\0')
+    {
+        if (*p == '.')
+        {
+            pt = p;
+            break;
+        }
+        p++;
+    }
+    if (pt == NULL)
+        return;
+    len1 = pt - str;
+    len2 = strlen(pt + 1);
+    if (len1 > 0 && len2 > 0)
+    {
+        *prefix = malloc(len1 + 1);
+        memcpy(*prefix, str, len1);
+        *(*prefix + len1) = '\0';
+        *table = malloc(len2 + 1);
+        strcpy(*table, pt + 1);
+    }
+}
+/* end sandro 2013-11-17 */
+
 static void
 convert_input_to_utf8 (char *buf, int maxlen)
 {
@@ -2141,8 +2186,10 @@ static char zHelp[] =
   "                         If TABLE specified, only show tables matching\n"
   "                         LIKE pattern TABLE.\n"
   ".separator STRING      Change separator used by output mode and .import\n"
+  ".shell CMD ARGS...     Run CMD ARGS... in a system shell\n"
   ".show                  Show the current values for various settings\n"
   ".stats ON|OFF          Turn stats on or off\n"
+  ".system CMD ARGS...    Run CMD ARGS... in a system shell\n"
   ".tables ?TABLE?        List names of tables\n"
   "                         If TABLE specified, only list tables matching\n"
   "                         LIKE pattern TABLE.\n"
@@ -2242,6 +2289,7 @@ static void open_db(struct callback_data *p){
           p->zDbFilename, sqlite3_errmsg(db));
       exit(1);
     }
+    spatialite_init_ex (p->db, splite_cache, (splite_silent == 0) ? 1 : 0);
 #ifndef SQLITE_OMIT_LOAD_EXTENSION
     sqlite3_enable_load_extension(p->db, 1);
 #endif
@@ -2662,7 +2710,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
           if (dxf == NULL)
               goto stop_dxf;
       /* attempting to parse the DXF input file */
-          if (gaiaParseDxfFile (dxf, dxf_path))
+          if (gaiaParseDxfFile_r (splite_cache, dxf, dxf_path))
           {
       /* loading into the DB */
               if (!gaiaLoadFromDxfParser (p->db, dxf, mode, append))
@@ -2782,17 +2830,29 @@ stop_dxf:
       }
     else if (c == 'd' && strncmp (azArg[0], "dropgeo", n) == 0 && nArg > 1)
       {
+          char *prefix;
+          char *table;
+          int ret;
           int cnt0 = sqlite3_total_changes(p->db);
-	  if (gaiaDropTable (p->db, azArg[1]))
+          split_drop_name(azArg[1], &prefix, &table);
+          if (prefix != NULL && table != NULL)
+              ret = gaiaDropTableEx (p->db, prefix, table);
+          else
+	      ret = gaiaDropTable (p->db, azArg[1]);
+          if (ret)
           {
               int cnt1 = sqlite3_total_changes(p->db);
               if (cnt1 > cnt0)
-                  fprintf(stderr, "SpatialTable \"%s\" succesfully removed\n", azArg[1]);
+                  fprintf(stderr, "SpatialTable %s succesfully removed\n", azArg[1]);
               else
-                  fprintf(stderr, "SpatialTable \"%s\" seems not to exist\n", azArg[1]);
+                  fprintf(stderr, "SpatialTable %s seems not to exist\n", azArg[1]);
           }
           else
-              fprintf(stderr, "ERROR: unable to remove SpatialTable \"%s\"\n", azArg[1]);
+              fprintf(stderr, "ERROR: unable to remove SpatialTable %s\n", azArg[1]);
+          if (prefix != NULL)
+              free(prefix);
+          if (table != NULL)
+              free(table);
       } else
 /* end sandro 2008-06-20 */
   if( c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0 && nArg>1 && nArg<4){
@@ -3406,6 +3466,27 @@ stop_dxf:
                      "%.*s", (int)sizeof(p->separator)-1, azArg[1]);
   }else
 
+  if( c=='s'
+   && (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)
+  ){
+    char *zCmd;
+    int i;
+    if( nArg<2 ){
+      fprintf(stderr, "Usage: .system COMMAND\n");
+      rc = 1;
+    }
+    else {
+      zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
+      for(i=2; i<nArg; i++){
+        zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
+                               zCmd, azArg[i]);
+      }
+      (void)system(zCmd);
+      sqlite3_free(zCmd);
+    }
+  }else
+
+
   if( c=='s' && strncmp(azArg[0], "show", n)==0 && nArg==1 ){
     int i;
     fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off");
@@ -4049,6 +4130,7 @@ static const char zOptions[] =
   "   -interactive         force interactive I/O\n"
   "   -line                set output mode to 'line'\n"
   "   -list                set output mode to 'list'\n"
+  "   -silent              suppress the welcome message\n"
 #ifdef SQLITE_ENABLE_MULTIPLEX
   "   -multiplex           enable the multiplexor VFS\n"
 #endif
@@ -4100,6 +4182,9 @@ int main(int argc, char **argv){
   char *zFirstCmd = 0;
   int i;
   int rc = 0;
+  
+/* initializing the SpatiaLite's internal cache */
+  splite_cache = spatialite_alloc_connection ();
 
   if( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)!=0 ){
     fprintf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
@@ -4112,8 +4197,13 @@ int main(int argc, char **argv){
 Sandro Furieri 30 May 2008
 ===========================
 registering the SpatiaLite extension
+2013-08-30: supporting "silent mode"
 */
-    spatialite_init (1);
+  for(i=1; i<argc && argv[i][0]=='-'; i++){
+    char *z = argv[i];
+    if( z[1]=='-' ){ z++; }
+    if( strcmp(z,"-silent")==0 ){ splite_silent = 1;}
+	}
 
   stdin_is_interactive = isatty(0);
 
@@ -4285,6 +4375,10 @@ registering the SpatiaLite extension
       data.statsOn = 1;
     }else if( strcmp(z,"-bail")==0 ){
       bail_on_error = 1;
+    }else if( strcmp(z,"-silent")==0 ){
+/* sandro 2013-08-30 */
+      splite_silent = 1;
+/* end sandro */
     }else if( strcmp(z,"-version")==0 ){
       printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid());
       return 0;
@@ -4362,6 +4456,7 @@ registering the SpatiaLite extension
         sqlite3_libversion(), sqlite3_sourceid()
       );
 */
+     open_db(&data);
      if (isatty (1))
           printf ("SQLite version ......: %s\n",
      sqlite3_libversion ());
@@ -4414,7 +4509,9 @@ Sandro Furieri 30 May 2008
 ===========================
 memory cleanup for SpatiaLite extension
 */
-    sqlite3_reset_auto_extension ();
+    
+  spatialite_cleanup_ex (splite_cache);
+  spatialite_shutdown ();
 
   return rc;
 }
diff --git a/spatialite_convert.c b/spatialite_convert.c
index 09f3dcf..bc427c1 100644
--- a/spatialite_convert.c
+++ b/spatialite_convert.c
@@ -2155,6 +2155,34 @@ copy_views_geometry_columns_4_3 (sqlite3 * handle)
 }
 
 static int
+check_views_geometry_columns (sqlite3 * handle)
+{
+/* may be v2.4 - testing for views_geometry_columns */
+    const char *sql;
+    char **results;
+    int ret;
+    int rows;
+    int columns;
+    int i;
+    char *errMsg = NULL;
+    int ok = 0;
+
+/* testing for an existing VIEWS_GEOMETRY_COLUMNS */
+    sql = "SELECT Count(*) FROM sqlite_master WHERE type = 'table' "
+	"AND Lower(name) = 'views_geometry_columns'";
+    ret = sqlite3_get_table (handle, sql, &results, &rows, &columns, &errMsg);
+    if (ret != SQLITE_OK)
+	return 0;
+    for (i = 1; i <= rows; i++)
+      {
+	  if (atoi (results[(i * columns)]) > 0)
+	      ok = 1;
+      }
+    sqlite3_free_table (results);
+    return ok;
+}
+
+static int
 cvt_views_geometry_columns (sqlite3 * handle, int in_version, int version)
 {
 /* converting VIEWS_GEOMETRY_COLUMNS */
@@ -2168,13 +2196,23 @@ cvt_views_geometry_columns (sqlite3 * handle, int in_version, int version)
       }
     else
       {
-	  /* if version=2 we'll simply create the table and exit */
-	  if (version == 3)
-	      ret = create_views_geometry_columns_3 (handle);
-	  if (version == 4)
-	      ret = create_views_geometry_columns_4 (handle);
-	  if (!ret)
-	      return 0;
+	  if (check_views_geometry_columns (handle))
+	    {
+		/* preparing the input table */
+		if (!prepare_input (handle, "views_geometry_columns"))
+		    return 0;
+	    }
+	  else
+	    {
+		/* if version=2 we'll simply create the table and exit */
+		if (version == 3)
+		    ret = create_views_geometry_columns_3 (handle);
+		if (version == 4)
+		    ret = create_views_geometry_columns_4 (handle);
+		if (!ret)
+		    return 0;
+		return 1;
+	    }
       }
     drop_views_geometry_columns (handle);
 
@@ -2191,31 +2229,26 @@ cvt_views_geometry_columns (sqlite3 * handle, int in_version, int version)
 
 /* copying any row */
     ret = 0;
-    if (in_version == 2)
-	ret = 1;
-    if (in_version == 3)
+    if (in_version == 4)
       {
 	  if (version == 2)
 	      ret = 1;
-	  if (version == 4)
-	      ret = copy_views_geometry_columns_3_4 (handle);
+	  if (version == 3)
+	      ret = copy_views_geometry_columns_4_3 (handle);
       }
-    if (in_version == 4)
+    else
       {
 	  if (version == 2)
 	      ret = 1;
-	  if (version == 3)
-	      ret = copy_views_geometry_columns_4_3 (handle);
+	  if (version == 4)
+	      ret = copy_views_geometry_columns_3_4 (handle);
       }
     if (!ret)
 	return 0;
 
-    if (in_version != 2)
-      {
-	  /* dropping the temporary input table */
-	  if (!drop_input_table (handle))
-	      return 0;
-      }
+    /* dropping the temporary input table */
+    if (!drop_input_table (handle))
+	return 0;
 
     return 1;
 }
@@ -3893,8 +3926,6 @@ static int
 cvt_extra_stuff (sqlite3 * handle, int version)
 {
 /* converting extra-sfuff Tables and Views */
-    int ret;
-
     if (version != 3)
 	drop_layer_statistics (handle);
 
@@ -4248,6 +4279,7 @@ register_virtual (sqlite3 * sqlite, const char *table, int version)
     int rows;
     int columns;
     int i;
+    int count = 0;
     char *errMsg = NULL;
     int xdims = -1;
 
@@ -4268,8 +4300,14 @@ register_virtual (sqlite3 * sqlite, const char *table, int version)
       {
 	  strcpy (gtype, results[(i * columns)]);
 	  srid = atoi (results[(i * columns) + 1]);
+	  count++;
       }
     sqlite3_free_table (results);
+    if (count == 0)
+      {
+	  /* empty table */
+	  return 1;
+      }
 
 /* normalized Geometry type */
     if (strcmp (gtype, "POINT") == 0)
@@ -7027,5 +7065,6 @@ main (int argc, char *argv[])
   end:
     sqlite3_close (handle);
     spatialite_cleanup_ex (cache);
+    spatialite_shutdown ();
     return 0;
 }
diff --git a/spatialite_dxf.c b/spatialite_dxf.c
index f5ba2d7..ed6d201 100644
--- a/spatialite_dxf.c
+++ b/spatialite_dxf.c
@@ -480,7 +480,7 @@ main (int argc, char *argv[])
     if (dxf == NULL)
 	goto stop;
 /* attempting to parse the DXF input file */
-    if (gaiaParseDxfFile (dxf, dxf_path))
+    if (gaiaParseDxfFile_r (cache, dxf, dxf_path))
       {
 	  /* loading into the DB */
 	  if (!gaiaLoadFromDxfParser (handle, dxf, mode, append))
@@ -541,5 +541,6 @@ main (int argc, char *argv[])
 		       sqlite3_errmsg (handle));
       }
     spatialite_cleanup_ex (cache);
+    spatialite_shutdown ();
     return 0;
 }
diff --git a/spatialite_gml.c b/spatialite_gml.c
index 72fc44c..dff2843 100644
--- a/spatialite_gml.c
+++ b/spatialite_gml.c
@@ -1941,5 +1941,6 @@ main (int argc, char *argv[])
 
     sqlite3_close (handle);
     spatialite_cleanup_ex (cache);
+    spatialite_shutdown ();
     return 0;
 }
diff --git a/spatialite_network.c b/spatialite_network.c
index bb2f896..784b95c 100644
--- a/spatialite_network.c
+++ b/spatialite_network.c
@@ -2123,5 +2123,6 @@ main (int argc, char *argv[])
     validate (path, table, from_column, to_column, cost_column, geom_column,
 	      name_column, oneway_tofrom, oneway_fromto, bidirectional,
 	      out_table, force_creation, a_star_supported);
+    spatialite_shutdown ();
     return 0;
 }
diff --git a/spatialite_osm_filter.c b/spatialite_osm_filter.c
index a219e2c..f609090 100644
--- a/spatialite_osm_filter.c
+++ b/spatialite_osm_filter.c
@@ -1864,5 +1864,6 @@ main (int argc, char *argv[])
     spatialite_cleanup_ex (cache);
     if (out != NULL)
 	fclose (out);
+    spatialite_shutdown ();
     return 0;
 }
diff --git a/spatialite_osm_map.c b/spatialite_osm_map.c
index fa757b9..71c566b 100644
--- a/spatialite_osm_map.c
+++ b/spatialite_osm_map.c
@@ -1549,22 +1549,32 @@ destroy_ring_refs (struct ring_refs *rings)
 
     if (rings == NULL)
 	return;
-    if (rings->id != NULL)
-	free (rings->id);
-    if (rings->found != NULL)
-	free (rings->found);
-    if (rings->outer != NULL)
-	free (rings->outer);
     if (rings->geom != NULL)
       {
 	  for (i = 0; i < rings->count; i++)
 	    {
 		g = *(rings->geom + i);
 		if (g)
-		    gaiaFreeGeomColl (g);
+		  {
+		      int j;
+		      sqlite3_int64 id = *(rings->id + i);
+		      gaiaFreeGeomColl (g);
+		      for (j = 0; j < rings->count; j++)
+			{
+			    sqlite3_int64 id2 = *(rings->id + j);
+			    if (id == id2)
+				*(rings->geom + j) = NULL;
+			}
+		  }
 	    }
 	  free (rings->geom);
       }
+    if (rings->id != NULL)
+	free (rings->id);
+    if (rings->found != NULL)
+	free (rings->found);
+    if (rings->outer != NULL)
+	free (rings->outer);
     free (rings);
 }
 
@@ -1806,7 +1816,7 @@ multipolygon_layer_insert (struct aux_params *params, const char *layer_name,
 			  sqlite3_bind_text (layer->ins_polygon_stmt, 3, name,
 					     strlen (name), SQLITE_STATIC);
 		      sqlite3_bind_blob (layer->ins_polygon_stmt, 4, blob,
-					 blob_size, SQLITE_STATIC);
+					 blob_size, free);
 		      ret = sqlite3_step (layer->ins_polygon_stmt);
 		      if (ret == SQLITE_DONE || ret == SQLITE_ROW)
 			  return 1;
@@ -1849,7 +1859,7 @@ multiline_generic_insert (struct aux_params *params,
 	      sqlite3_bind_text (params->ins_generic_linestring_stmt, 2, name,
 				 strlen (name), SQLITE_STATIC);
 	  sqlite3_bind_blob (params->ins_generic_linestring_stmt, 3, blob,
-			     blob_size, SQLITE_STATIC);
+			     blob_size, free);
 	  ret = sqlite3_step (params->ins_generic_linestring_stmt);
 	  if (ret == SQLITE_DONE || ret == SQLITE_ROW)
 	      return 1;
@@ -1889,7 +1899,7 @@ multipolygon_generic_insert (struct aux_params *params,
 	      sqlite3_bind_text (params->ins_generic_polygon_stmt, 2, name,
 				 strlen (name), SQLITE_STATIC);
 	  sqlite3_bind_blob (params->ins_generic_polygon_stmt, 3, blob,
-			     blob_size, SQLITE_STATIC);
+			     blob_size, free);
 	  ret = sqlite3_step (params->ins_generic_polygon_stmt);
 	  if (ret == SQLITE_DONE || ret == SQLITE_ROW)
 	      return 1;
@@ -2832,5 +2842,6 @@ main (int argc, char *argv[])
     db_vacuum (handle);
     sqlite3_close (handle);
     spatialite_cleanup_ex (cache);
+    spatialite_shutdown ();
     return 0;
 }
diff --git a/spatialite_osm_net.c b/spatialite_osm_net.c
index f7bf0b3..bbff0b1 100644
--- a/spatialite_osm_net.c
+++ b/spatialite_osm_net.c
@@ -2747,5 +2747,6 @@ main (int argc, char *argv[])
     sqlite3_close (handle);
     spatialite_cleanup_ex (cache);
     free_params (&params);
+    spatialite_shutdown ();
     return 0;
 }
diff --git a/spatialite_osm_raw.c b/spatialite_osm_raw.c
index 1ef9e40..5d292ec 100644
--- a/spatialite_osm_raw.c
+++ b/spatialite_osm_raw.c
@@ -1225,5 +1225,6 @@ main (int argc, char *argv[])
 /* closing the DB connection */
     sqlite3_close (handle);
     spatialite_cleanup_ex (cache);
+    spatialite_shutdown ();
     return 0;
 }
diff --git a/spatialite_tool.c b/spatialite_tool.c
index 17f6d7e..2a73751 100644
--- a/spatialite_tool.c
+++ b/spatialite_tool.c
@@ -539,5 +539,6 @@ main (int argc, char *argv[])
 		       coerce2d, compressed);
     if (export)
 	do_export (db_path, shp_path, table, column, charset, type);
+    spatialite_shutdown ();
     return 0;
 }
diff --git a/spatialite_xml_collapse.c b/spatialite_xml_collapse.c
new file mode 100644
index 0000000..b94b76f
--- /dev/null
+++ b/spatialite_xml_collapse.c
@@ -0,0 +1,2408 @@
+/* 
+/ spatialite_xml_collapse
+/
+/ a tool performing post-processing tasks after importing
+/ several XML files into SQLite tables
+/
+/ version 1.0, 2013 August 20
+/
+/ Author: Sandro Furieri a.furieri at lqt.it
+/
+/ Copyright (C) 2013  Alessandro Furieri
+/
+/    This program is free software: you can redistribute it and/or modify
+/    it under the terms of the GNU General Public License as published by
+/    the Free Software Foundation, either version 3 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 General Public License for more details.
+/
+/    You should have received a copy of the GNU General Public License
+/    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/
+*/
+
+#if defined(_WIN32) && !defined(__MINGW32__)
+/* MSVC strictly requires this include [off_t] */
+#include <sys/types.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <sqlite3.h>
+#include <spatialite.h>
+
+#define ARG_NONE	0
+#define ARG_DB_PATH	1
+#define ARG_CACHE_SIZE 2
+#define ARG_NAME_LEVEL 3
+
+struct resultset_values
+{
+/* a struct wrapping values from a resultset */
+    int type;
+    sqlite3_int64 int_value;
+    double dbl_value;
+    unsigned char *txt_blob_value;
+    int txt_blob_size;
+};
+
+struct resultset_comparator
+{
+/* object for comparing two rows of the same resultset */
+    struct resultset_values *previous;
+    struct resultset_values *current;
+    int num_columns;
+    sqlite3_int64 previous_rowid;
+    sqlite3_int64 current_rowid;
+};
+
+struct xml_attribute
+{
+/* a struct wrapping an XML attribute (column name) */
+    char *attr_name;
+    char *sql_name;
+    int main_collapsed;
+    int already_defined;
+    int datatype;
+    sqlite3_int64 int_value;
+    double double_value;
+    const unsigned char *text_value;
+    const unsigned char *blob_value;
+    int blob_size;
+    char *xml_reference;
+    struct xml_attribute *next;
+};
+
+struct new_attributes
+{
+/* containing struct for XML attributes (columns) to be added */
+    struct xml_attribute *first;
+    struct xml_attribute *last;
+    int collision;
+};
+
+struct child_reference
+{
+/* an XML child reference */
+    struct xml_table *child;
+    struct child_reference *next;
+};
+
+struct xml_table
+{
+/* a struct wrapping an XML table */
+    char *table_name;
+    char *parent_table;
+    char *tag_ns;
+    char *tag_name;
+    char *geometry;
+    struct xml_table *parent;
+    struct child_reference *first;
+    struct child_reference *last;
+    int done;
+    int level;
+    struct xml_table *next;
+};
+
+struct xml_geometry
+{
+/* a struct wrapping some BLOB geometry */
+    char *table_name;
+    char *geometry;
+    char *type;
+    int srid;
+    char *dims;
+    struct xml_geometry *next;
+};
+
+struct xml_tables_list
+{
+/* linked list of XML tables */
+    struct xml_table *first;
+    struct xml_table *last;
+    struct xml_geometry *first_geom;
+    struct xml_geometry *last_geom;
+};
+
+static struct resultset_comparator *
+create_resultset_comparator (int columns)
+{
+/* creating an empty resultset comparator object */
+    int i;
+    struct resultset_comparator *p =
+	malloc (sizeof (struct resultset_comparator));
+    p->num_columns = columns;
+    p->previous_rowid = -1;
+    p->current_rowid = -1;
+    p->previous = malloc (sizeof (struct resultset_values) * columns);
+    p->current = malloc (sizeof (struct resultset_values) * columns);
+    for (i = 0; i < columns; i++)
+      {
+	  struct resultset_values *value = p->previous + i;
+	  value->type = SQLITE_NULL;
+	  value->txt_blob_value = NULL;
+	  value = p->current + i;
+	  value->type = SQLITE_NULL;
+	  value->txt_blob_value = NULL;
+      }
+    return p;
+}
+
+static void
+destroy_resultset_comparator (struct resultset_comparator *ptr)
+{
+/* memory cleanup - destroying a resultset comparator object */
+    int i;
+    if (ptr == NULL)
+	return;
+    for (i = 0; i < ptr->num_columns; i++)
+      {
+	  struct resultset_values *value = ptr->previous + i;
+	  if (value->txt_blob_value != NULL)
+	      free (value->txt_blob_value);
+	  value = ptr->current + i;
+	  if (value->txt_blob_value != NULL)
+	      free (value->txt_blob_value);
+      }
+    if (ptr->previous != NULL)
+	free (ptr->previous);
+    if (ptr->current != NULL)
+	free (ptr->current);
+    free (ptr);
+}
+
+static void
+save_row_from_resultset (struct resultset_comparator *ptr, sqlite3_stmt * stmt)
+{
+/* saving the current row values */
+    int i;
+    int size;
+    const unsigned char *p;
+    if (ptr == NULL)
+	return;
+    ptr->current_rowid = sqlite3_column_int64 (stmt, 0);
+    for (i = 0; i < ptr->num_columns; i++)
+      {
+	  struct resultset_values *value = ptr->current + i;
+	  value->type = sqlite3_column_type (stmt, i + 1);
+	  switch (value->type)
+	    {
+	    case SQLITE_INTEGER:
+		value->int_value = sqlite3_column_int64 (stmt, i + 1);
+		break;
+	    case SQLITE_FLOAT:
+		value->dbl_value = sqlite3_column_double (stmt, i + 1);
+		break;
+	    case SQLITE_TEXT:
+		p = sqlite3_column_text (stmt, i + 1);
+		size = strlen ((const char *) p);
+		value->txt_blob_value = malloc (size + 1);
+		strcpy ((char *) (value->txt_blob_value), (const char *) p);
+		break;
+	    case SQLITE_BLOB:
+		p = sqlite3_column_blob (stmt, i + 1);
+		size = sqlite3_column_bytes (stmt, i + 1);
+		value->txt_blob_value = malloc (size);
+		memcpy (value->txt_blob_value, p, size);
+		value->txt_blob_size = size;
+		break;
+	    };
+      }
+}
+
+static int
+resultset_rows_equals (struct resultset_comparator *ptr)
+{
+/* comparing the current and previous row from the resultset */
+    int i;
+    if (ptr == NULL)
+	return 0;
+    for (i = 0; i < ptr->num_columns; i++)
+      {
+	  struct resultset_values *val_prev = ptr->previous + i;
+	  struct resultset_values *val_curr = ptr->current + i;
+	  if (val_prev->type != val_curr->type)
+	      return 0;
+	  switch (val_prev->type)
+	    {
+	    case SQLITE_INTEGER:
+		if (val_prev->int_value != val_curr->int_value)
+		    return 0;
+		break;
+	    case SQLITE_FLOAT:
+		if (val_prev->dbl_value != val_curr->dbl_value)
+		    return 0;
+		break;
+	    case SQLITE_TEXT:
+		if (strcmp
+		    ((const char *) (val_prev->txt_blob_value),
+		     (const char *) (val_curr->txt_blob_value)) != 0)
+		    return 0;
+		break;
+	    case SQLITE_BLOB:
+		if (val_prev->txt_blob_size != val_curr->txt_blob_size)
+		    return 0;
+		if (memcmp
+		    (val_prev->txt_blob_value, val_curr->txt_blob_value,
+		     val_curr->txt_blob_size) != 0)
+		    return 0;
+		break;
+	    };
+      }
+    return 1;
+}
+
+static sqlite3_int64
+get_current_resultset_rowid (struct resultset_comparator *ptr)
+{
+/* returns the current ROWID */
+    if (ptr == NULL)
+	return -1;
+    return ptr->current_rowid;
+}
+
+static void
+reset_resultset_current_row (struct resultset_comparator *ptr)
+{
+/* resetting the resultset current row values */
+    int i;
+    if (ptr == NULL)
+	return;
+    ptr->current_rowid = -1;
+    for (i = 0; i < ptr->num_columns; i++)
+      {
+	  struct resultset_values *value = ptr->current + i;
+	  value->type = SQLITE_NULL;
+	  if (value->txt_blob_value != NULL)
+	      free (value->txt_blob_value);
+	  value->txt_blob_value = NULL;
+      }
+}
+
+static void
+swap_resultset_rows (struct resultset_comparator *ptr)
+{
+/* resetting the resultset comparator */
+    int i;
+    if (ptr == NULL)
+	return;
+    ptr->previous_rowid = ptr->current_rowid;
+    ptr->current_rowid = -1;
+    for (i = 0; i < ptr->num_columns; i++)
+      {
+	  struct resultset_values *val_prev = ptr->previous + i;
+	  struct resultset_values *val_curr = ptr->current + i;
+	  if (val_prev->txt_blob_value != NULL)
+	      free (val_prev->txt_blob_value);
+	  val_prev->type = val_curr->type;
+	  val_prev->int_value = val_curr->int_value;
+	  val_prev->dbl_value = val_curr->dbl_value;
+	  val_prev->txt_blob_value = val_curr->txt_blob_value;
+	  val_prev->txt_blob_size = val_curr->txt_blob_size;
+	  val_curr->type = SQLITE_NULL;
+	  val_curr->txt_blob_value = NULL;
+      }
+}
+
+static void
+destroy_child_reference (struct child_reference *p)
+{
+/* memory cleanup - destroying a child reference */
+    if (p == NULL)
+	return;
+    free (p);
+}
+
+static struct xml_table *
+alloc_xml_table (const char *table, const char *parent, const char *tag_ns,
+		 const char *tag_name, const char *geometry, int level)
+{
+/* allocating and initializing an XML table */
+    int len;
+    struct xml_table *p = malloc (sizeof (struct xml_table));
+    len = strlen (table);
+    p->table_name = malloc (len + 1);
+    strcpy (p->table_name, table);
+    if (parent == NULL)
+	p->parent_table = NULL;
+    else
+      {
+	  len = strlen (parent);
+	  p->parent_table = malloc (len + 1);
+	  strcpy (p->parent_table, parent);
+      }
+    if (tag_ns == NULL)
+	p->tag_ns = NULL;
+    else
+      {
+	  len = strlen (tag_ns);
+	  p->tag_ns = malloc (len + 1);
+	  strcpy (p->tag_ns, tag_ns);
+      }
+    len = strlen (tag_name);
+    p->tag_name = malloc (len + 1);
+    strcpy (p->tag_name, tag_name);
+    if (geometry == NULL)
+	p->geometry = NULL;
+    else
+      {
+	  len = strlen (geometry);
+	  p->geometry = malloc (len + 1);
+	  strcpy (p->geometry, geometry);
+      }
+    p->parent = NULL;
+    p->first = NULL;
+    p->last = NULL;
+    p->done = 0;
+    p->level = level;
+    p->next = NULL;
+    return p;
+}
+
+static void
+destroy_xml_table (struct xml_table *p)
+{
+/* memory cleanup - destroying an XML table */
+    struct child_reference *pc;
+    struct child_reference *pcn;
+    if (p == NULL)
+	return;
+    if (p->table_name)
+	free (p->table_name);
+    if (p->parent_table)
+	free (p->parent_table);
+    if (p->tag_ns)
+	free (p->tag_ns);
+    if (p->tag_name)
+	free (p->tag_name);
+    if (p->geometry)
+	free (p->geometry);
+    pc = p->first;
+    while (pc != NULL)
+      {
+	  pcn = pc->next;
+	  destroy_child_reference (pc);
+	  pc = pcn;
+      }
+    free (p);
+}
+
+static struct xml_geometry *
+alloc_xml_geometry (const char *table, const char *geometry)
+{
+/* allocating and initializing an XML geometry */
+    int len;
+    struct xml_geometry *p = malloc (sizeof (struct xml_geometry));
+    len = strlen (table);
+    p->table_name = malloc (len + 1);
+    strcpy (p->table_name, table);
+    len = strlen (geometry);
+    p->geometry = malloc (len + 1);
+    strcpy (p->geometry, geometry);
+    p->type = NULL;
+    p->srid = -1;
+    p->dims = NULL;
+    p->next = NULL;
+    return p;
+}
+
+static void
+destroy_xml_geometry (struct xml_geometry *p)
+{
+/* memory cleanup - destroying an XML Geometry */
+    if (p == NULL)
+	return;
+    if (p->table_name)
+	free (p->table_name);
+    if (p->geometry)
+	free (p->geometry);
+    if (p->type)
+	free (p->type);
+    if (p->dims)
+	free (p->dims);
+    free (p);
+}
+
+static struct xml_tables_list *
+alloc_xml_tables (void)
+{
+/* creating an empty list */
+    struct xml_tables_list *p = malloc (sizeof (struct xml_tables_list));
+    p->first = NULL;
+    p->last = NULL;
+    p->first_geom = NULL;
+    p->last_geom = NULL;
+    return p;
+}
+
+static void
+destroy_xml_tables (struct xml_tables_list *p)
+{
+/* memory cleanup - destroying the list */
+    struct xml_table *pt;
+    struct xml_table *ptn;
+    struct xml_geometry *pg;
+    struct xml_geometry *pgn;
+    if (p == NULL)
+	return;
+    pt = p->first;
+    while (pt != NULL)
+      {
+	  ptn = pt->next;
+	  destroy_xml_table (pt);
+	  pt = ptn;
+      }
+    pg = p->first_geom;
+    while (pg != NULL)
+      {
+	  pgn = pg->next;
+	  destroy_xml_geometry (pg);
+	  pg = pgn;
+      }
+    free (p);
+}
+
+static void
+add_xml_table (struct xml_tables_list *list, const char *table,
+	       const char *parent, const char *tag_ns, const char *tag_name,
+	       const char *geometry, int level)
+{
+/* adds an XML table into the list */
+    struct xml_table *p =
+	alloc_xml_table (table, parent, tag_ns, tag_name, geometry, level);
+    if (list->first == NULL)
+	list->first = p;
+    if (list->last != NULL)
+	list->last->next = p;
+    list->last = p;
+}
+
+static void
+add_xml_geometry (struct xml_tables_list *list, const char *table,
+		  const char *geometry)
+{
+/* adds an XML geometry into the list */
+    struct xml_geometry *p = alloc_xml_geometry (table, geometry);
+    if (list->first_geom == NULL)
+	list->first_geom = p;
+    if (list->last_geom != NULL)
+	list->last_geom->next = p;
+    list->last_geom = p;
+}
+
+static void
+add_child (struct xml_tables_list *list, struct xml_table *child,
+	   const char *parent)
+{
+/* inserting a child into the parent */
+    struct xml_table *p = list->first;
+    while (p != NULL)
+      {
+	  if (strcasecmp (p->table_name, parent) == 0)
+	    {
+		struct child_reference *ref =
+		    malloc (sizeof (struct child_reference));
+		ref->child = child;
+		ref->next = NULL;
+		if (p->first == NULL)
+		    p->first = ref;
+		if (p->last != NULL)
+		    p->last->next = ref;
+		p->last = ref;
+		child->parent = p;
+		return;
+	    }
+	  p = p->next;
+      }
+}
+
+static void
+identify_childs (struct xml_tables_list *list)
+{
+/* identifying parent-child relationships */
+    struct xml_table *p = list->first;
+    while (p != NULL)
+      {
+	  if (p->parent_table != NULL)
+	      add_child (list, p, p->parent_table);
+	  p = p->next;
+      }
+}
+
+static void
+add_attribute (struct new_attributes *p, const char *name, int main)
+{
+/* adding a new XML Attribute (column) into the container */
+    int len;
+    int i;
+    struct xml_attribute *attr = malloc (sizeof (struct xml_attribute));
+    len = strlen (name);
+    attr->attr_name = malloc (len + 1);
+    strcpy (attr->attr_name, name);
+    for (i = 0; i < len; i++)
+      {
+	  char c = *(attr->attr_name + i);
+	  if (c >= 'A' && c <= 'Z')
+	      *(attr->attr_name + i) = c - 'A' + 'a';
+      }
+    attr->main_collapsed = main;
+    attr->already_defined = 0;
+    attr->datatype = SQLITE_NULL;
+    attr->xml_reference = NULL;
+    attr->next = NULL;
+    if (p->first == NULL)
+	p->first = attr;
+    if (p->last != NULL)
+	p->last->next = attr;
+    p->last = attr;
+}
+
+static void
+destroy_attribute (struct xml_attribute *attr)
+{
+/* memory cleanup: destroying an XML Attribute (column) */
+    if (attr == NULL)
+	return;
+    if (attr->attr_name != NULL)
+	free (attr->attr_name);
+    if (attr->xml_reference != NULL)
+	free (attr->xml_reference);
+    free (attr);
+}
+
+static struct new_attributes *
+alloc_new_attributes (void)
+{
+/* creating an empty container */
+    struct new_attributes *p = malloc (sizeof (struct new_attributes));
+    p->first = NULL;
+    p->last = NULL;
+    p->collision = 0;
+    return p;
+}
+
+static void
+destroy_new_attributes (struct new_attributes *p)
+{
+/* memory cleanup: destroying a container */
+    struct xml_attribute *pa;
+    struct xml_attribute *pan;
+    if (p == NULL)
+	return;
+    pa = p->first;
+    while (pa != NULL)
+      {
+	  pan = pa->next;
+	  destroy_attribute (pa);
+	  pa = pan;
+      }
+    free (p);
+}
+
+static void
+check_attribute (struct new_attributes *p, const char *name)
+{
+/* checks if an Attribute/Column name is already defined */
+    struct xml_attribute *attr = p->first;
+    while (attr != NULL)
+      {
+	  if (strcasecmp (attr->attr_name, name) == 0)
+	    {
+		attr->already_defined = 1;
+		p->collision = 1;
+	    }
+	  attr = attr->next;
+      }
+}
+
+static void
+reset_attribute_values (struct new_attributes *p)
+{
+/* resetting all values as NULL */
+    struct xml_attribute *attr = p->first;
+    while (attr != NULL)
+      {
+	  attr->datatype = SQLITE_NULL;
+	  attr = attr->next;
+      }
+}
+
+static void
+set_int_value (struct new_attributes *p, const char *name,
+	       sqlite3_int64 int_value)
+{
+/* setting an INT-64 attribute value */
+    struct xml_attribute *attr = p->first;
+    while (attr != NULL)
+      {
+	  if (strcasecmp (attr->attr_name, name) == 0)
+	    {
+		attr->datatype = SQLITE_INTEGER;
+		attr->int_value = int_value;
+		break;
+	    }
+	  attr = attr->next;
+      }
+}
+
+static void
+set_double_value (struct new_attributes *p, const char *name,
+		  double double_value)
+{
+/* setting a FLOATING POINT (DOUBLE) attribute value */
+    struct xml_attribute *attr = p->first;
+    while (attr != NULL)
+      {
+	  if (strcasecmp (attr->attr_name, name) == 0)
+	    {
+		attr->datatype = SQLITE_FLOAT;
+		attr->double_value = double_value;
+		break;
+	    }
+	  attr = attr->next;
+      }
+}
+
+static void
+set_text_value (struct new_attributes *p, const char *name,
+		const unsigned char *text_value)
+{
+/* setting a TEXT attribute value */
+    struct xml_attribute *attr = p->first;
+    while (attr != NULL)
+      {
+	  if (strcasecmp (attr->attr_name, name) == 0)
+	    {
+		attr->datatype = SQLITE_TEXT;
+		attr->text_value = text_value;
+		break;
+	    }
+	  attr = attr->next;
+      }
+}
+
+static void
+set_blob_value (struct new_attributes *p, const char *name,
+		const unsigned char *blob_value, int blob_size)
+{
+/* setting a BLOB attribute value */
+    struct xml_attribute *attr = p->first;
+    while (attr != NULL)
+      {
+	  if (strcasecmp (attr->attr_name, name) == 0)
+	    {
+		attr->datatype = SQLITE_BLOB;
+		attr->blob_value = blob_value;
+		attr->blob_size = blob_size;
+		break;
+	    }
+	  attr = attr->next;
+      }
+}
+
+static char *
+get_main_attribute (struct new_attributes *p)
+{
+/* return the name of the "main" attribute */
+    struct xml_attribute *attr = p->first;
+    while (attr != NULL)
+      {
+	  if (attr->main_collapsed == 1)
+	      return attr->attr_name;
+	  attr = attr->next;
+      }
+    return NULL;
+}
+
+static int
+do_delete_duplicates2 (sqlite3 * sqlite, sqlite3_int64 rowid,
+		       sqlite3_stmt * stmt1, int *count)
+{
+/* deleting duplicate rows [actual delete] */
+    int ret;
+
+    *count = 0;
+    sqlite3_reset (stmt1);
+    sqlite3_clear_bindings (stmt1);
+    sqlite3_bind_int64 (stmt1, 1, rowid);
+    ret = sqlite3_step (stmt1);
+    if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+	;
+    else
+      {
+	  fprintf (stderr, "SQL error: %s\n", sqlite3_errmsg (sqlite));
+	  goto error;
+      }
+    *count = 1;
+    return 1;
+
+  error:
+    *count = 0;
+
+    return 0;
+}
+
+static void
+do_delete_duplicates (sqlite3 * sqlite, const char *sql,
+		      const char *sql_del, int *count)
+{
+/* deleting duplicate rows */
+    sqlite3_stmt *stmt1 = NULL;
+    sqlite3_stmt *stmt2 = NULL;
+    int ret;
+    int xcnt;
+    int cnt = 0;
+    char *sql_err = NULL;
+    struct resultset_comparator *rs_obj = NULL;
+
+    *count = 0;
+
+/* the complete operation is handled as an unique SQL Transaction */
+    ret = sqlite3_exec (sqlite, "BEGIN", NULL, NULL, &sql_err);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "BEGIN TRANSACTION error: %s\n", sql_err);
+	  sqlite3_free (sql_err);
+	  return;
+      }
+/* preparing the main SELECT statement */
+    ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt1, NULL);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SQL error: %s\n", sqlite3_errmsg (sqlite));
+	  return;
+      }
+/* preparing the DELETE statement */
+    ret = sqlite3_prepare_v2 (sqlite, sql_del, strlen (sql_del), &stmt2, NULL);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SQL error: %s\n", sqlite3_errmsg (sqlite));
+	  goto error;
+      }
+
+    rs_obj = create_resultset_comparator (sqlite3_column_count (stmt1) - 1);
+    while (1)
+      {
+	  /* fetching the result set rows */
+	  ret = sqlite3_step (stmt1);
+	  if (ret == SQLITE_DONE)
+	      break;		/* end of result set */
+	  if (ret == SQLITE_ROW)
+	    {
+		/* fetching a row */
+		save_row_from_resultset (rs_obj, stmt1);
+		if (resultset_rows_equals (rs_obj))
+		  {
+		      if (do_delete_duplicates2
+			  (sqlite, get_current_resultset_rowid (rs_obj), stmt2,
+			   &xcnt))
+			{
+			    cnt += xcnt;
+			    reset_resultset_current_row (rs_obj);
+			    continue;
+			}
+		      else
+			  goto error;
+		  }
+		swap_resultset_rows (rs_obj);
+	    }
+	  else
+	    {
+		fprintf (stderr, "SQL error: %s\n", sqlite3_errmsg (sqlite));
+		goto error;
+	    }
+      }
+    destroy_resultset_comparator (rs_obj);
+
+    sqlite3_finalize (stmt1);
+    sqlite3_finalize (stmt2);
+
+/* confirm the still pending Transaction */
+    ret = sqlite3_exec (sqlite, "COMMIT", NULL, NULL, &sql_err);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "COMMIT TRANSACTION error: %s\n", sql_err);
+	  sqlite3_free (sql_err);
+	  return;
+      }
+
+    *count = cnt;
+    return;
+
+  error:
+    *count = 0;
+    if (stmt1)
+	sqlite3_finalize (stmt1);
+    if (stmt2)
+	sqlite3_finalize (stmt2);
+    if (rs_obj != NULL)
+	destroy_resultset_comparator (rs_obj);
+
+/* performing a ROLLBACK anyway */
+    ret = sqlite3_exec (sqlite, "ROLLBACK", NULL, NULL, &sql_err);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "ROLLBACK TRANSACTION error: %s\n", sql_err);
+	  sqlite3_free (sql_err);
+      }
+}
+
+static char *
+eval_table (sqlite3 * db_handle, char *table)
+{
+/* preparing the column list for Delete Duplicates */
+    int ret;
+    char *sql;
+    char **results;
+    int rows;
+    int columns;
+    int i;
+    char *list = NULL;
+
+/* testing if the column/table really exists */
+    sql = sqlite3_mprintf ("PRAGMA table_info(\"%s\")", table);
+    ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+	goto done;
+    if (rows < 1)
+	;
+    else
+      {
+	  for (i = 1; i <= rows; i++)
+	    {
+		const char *name = results[(i * columns) + 1];
+		if (strcmp (name, "node_id") == 0)
+		    continue;
+		if (strcmp (name, "parent_id") == 0)
+		    continue;
+		if (list == NULL)
+		    list = sqlite3_mprintf ("\"%s\"", name);
+		else
+		  {
+		      char *tmp = sqlite3_mprintf ("%s, \"%s\"", list, name);
+		      sqlite3_free (list);
+		      list = tmp;
+		  }
+	    }
+      }
+    sqlite3_free_table (results);
+  done:
+    return list;
+}
+
+static void
+remove_duplicates (sqlite3 * db_handle, struct xml_table *table)
+{
+/* attempting to delete Duplicated rows from a table */
+    int count;
+    char *sql;
+    char *sql_del;
+    char *column_list = eval_table (db_handle, table->table_name);
+    if (column_list == NULL)
+      {
+	  table->done = 1;
+	  return;
+      }
+    sql = sqlite3_mprintf ("SELECT ROWID, %s FROM \"%s\" ORDER BY %s, ROWID",
+			   column_list, table->table_name, column_list);
+    sqlite3_free (column_list);
+    sql_del =
+	sqlite3_mprintf ("DELETE FROM \"%s\" WHERE ROWID = ?",
+			 table->table_name);
+    do_delete_duplicates (db_handle, sql, sql_del, &count);
+    if (!count)
+	printf ("No duplicated rows found in: %s\n", table->table_name);
+    else
+	printf ("%9d duplicated rows deleted from: %s\n", count,
+		table->table_name);
+    fflush (stdout);
+    sqlite3_free (sql);
+    sqlite3_free (sql_del);
+    table->done = 1;
+}
+
+static void
+recover_geometry (sqlite3 * db_handle, struct xml_geometry *geom)
+{
+/* recovering a full Geometry Column */
+    int ret;
+    char *err_msg;
+    char *sql;
+
+    printf ("Recovering Geometry:    %s.%s\n", geom->table_name,
+	    geom->geometry);
+    fflush (stdout);
+
+    sql = sqlite3_mprintf ("SELECT RecoverGeometryColumn(%Q, %Q, %d, %Q, %Q)",
+			   geom->table_name, geom->geometry, geom->srid,
+			   geom->type, geom->dims);
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "RecoverGeometryColumn error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  return;
+      }
+
+    fprintf (stderr, "Creating Spatial Index: %s.%s\n", geom->table_name,
+	     geom->geometry);
+
+    sql = sqlite3_mprintf ("SELECT CreateSpatialIndex(%Q, %Q)",
+			   geom->table_name, geom->geometry);
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CreateSpatialIndex error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  return;
+      }
+}
+
+static void
+check_geometry (sqlite3 * db_handle, struct xml_geometry *geom)
+{
+/* checks if a geometry could be recovered */
+    int ret;
+    char *sql;
+    char **results;
+    int rows;
+    int columns;
+    int i;
+    int exists = 0;
+    int registered = 0;
+
+/* testing if the column/table really exists */
+    sql = sqlite3_mprintf ("PRAGMA table_info(\"%s\")", geom->table_name);
+    ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+	goto done1;
+    if (rows < 1)
+	;
+    else
+      {
+	  for (i = 1; i <= rows; i++)
+	    {
+		const char *name = results[(i * columns) + 1];
+		if (strcmp (name, geom->geometry) == 0)
+		    exists = 1;
+	    }
+      }
+    sqlite3_free_table (results);
+  done1:
+
+/* testing if the geometry isn't yet registered */
+    sql = sqlite3_mprintf ("SELECT f_geometry_column FROM geometry_columns "
+			   "WHERE Lower(f_table_name) = Lower(%Q) AND "
+			   "Lower(f_geometry_column) = Lower(%Q)",
+			   geom->table_name, geom->geometry);
+    ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  registered = 1;
+	  goto done2;
+      }
+    if (rows < 1)
+	;
+    else
+      {
+	  for (i = 1; i <= rows; i++)
+	    {
+		const char *name = results[(i * columns) + 0];
+		if (strcmp (name, geom->geometry) == 0)
+		    registered = 1;
+	    }
+      }
+    sqlite3_free_table (results);
+  done2:
+    if (exists && !registered)
+	;
+    else
+	return;
+
+/* testing if the geometry could really be recovered */
+    sql = sqlite3_mprintf ("SELECT DISTINCT ST_GeometryType(\"%s\"), "
+			   "ST_Srid(\"%s\"), CoordDimension(\"%s\") "
+			   "FROM \"%s\"", geom->geometry, geom->geometry,
+			   geom->geometry, geom->table_name);
+    ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+	return;
+    if (rows != 1)
+	;
+    else
+      {
+	  for (i = 1; i <= rows; i++)
+	    {
+		int len;
+		int i2;
+		const char *type = results[(i * columns) + 0];
+		const char *srid = results[(i * columns) + 1];
+		const char *dims = results[(i * columns) + 2];
+		if (geom->type != NULL)
+		    free (geom->type);
+		len = strlen (type);
+		geom->type = malloc (len + 1);
+		strcpy (geom->type, type);
+		for (i2 = 0; i2 < len; i2++)
+		  {
+		      if (*(geom->type + i2) == ' ')
+			  *(geom->type + i2) = '\0';
+		  }
+		geom->srid = atoi (srid);
+		if (geom->dims != NULL)
+		    free (geom->dims);
+		len = strlen (dims);
+		geom->dims = malloc (len + 1);
+		strcpy (geom->dims, dims);
+	    }
+      }
+    sqlite3_free_table (results);
+}
+
+static int
+collapse_table (sqlite3 * db_handle, int journal_off,
+		struct new_attributes *list, const char *table,
+		const char *parent, struct xml_table *tbl)
+{
+/* attempting to collapse some Child table into the Parent */
+    int ret;
+    char *err_msg = NULL;
+    char *sql;
+    char *sql1;
+    struct xml_attribute *attr;
+    sqlite3_stmt *sel_stmt = NULL;
+    sqlite3_stmt *upd_stmt = NULL;
+    int error = 0;
+    sqlite3_int64 pk_value;
+    const unsigned char *main_value;
+    int i;
+    char *tag_child;
+    char *tag_parent;
+
+    if (tbl->tag_ns == NULL)
+	tag_child = sqlite3_mprintf ("<%s>", tbl->tag_name);
+    else
+	tag_child = sqlite3_mprintf ("<%s:%s>", tbl->tag_ns, tbl->tag_name);
+    if (tbl->parent->tag_ns == NULL)
+	tag_parent = sqlite3_mprintf ("<%s>", tbl->parent->tag_name);
+    else
+	tag_parent =
+	    sqlite3_mprintf ("<%s:%s>", tbl->parent->tag_ns,
+			     tbl->parent->tag_name);
+    printf ("Collapsing %s%s\n", tag_parent, tag_child);
+    fflush (stdout);
+    sqlite3_free (tag_child);
+    sqlite3_free (tag_parent);
+
+    sql = sqlite3_mprintf ("SELECT parent_id, node_value");
+    attr = list->first;
+    while (attr != NULL)
+      {
+	  if (attr->main_collapsed)
+	    {
+		/* skipping the "main" attribute (child tag name) */
+		attr = attr->next;
+		continue;
+	    }
+	  sql1 =
+	      sqlite3_mprintf ("%s, \"%s\" AS \"%s\"", sql, attr->attr_name,
+			       attr->attr_name);
+	  sqlite3_free (sql);
+	  sql = sql1;
+	  attr = attr->next;
+      }
+    sql1 = sqlite3_mprintf ("%s FROM \"%s\"", sql, table);
+    sqlite3_free (sql);
+    sql = sql1;
+    ret = sqlite3_prepare_v2 (db_handle, sql, strlen (sql), &sel_stmt, NULL);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SELECT FROM Child error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  error = 1;
+	  goto stop;
+      }
+
+    sql =
+	sqlite3_mprintf ("UPDATE \"%s\" SET \"%s\" = ?", parent,
+			 get_main_attribute (list));
+    attr = list->first;
+    while (attr != NULL)
+      {
+	  if (attr->main_collapsed)
+	    {
+		/* skipping the "main" attribute (child tag name) */
+		attr = attr->next;
+		continue;
+	    }
+	  sql1 = sqlite3_mprintf ("%s, \"%s\" = ?", sql, attr->attr_name);
+	  sqlite3_free (sql);
+	  sql = sql1;
+	  attr = attr->next;
+      }
+    sql1 = sqlite3_mprintf ("%s WHERE node_id = ?", sql);
+    sqlite3_free (sql);
+    sql = sql1;
+    ret = sqlite3_prepare_v2 (db_handle, sql, strlen (sql), &upd_stmt, NULL);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "UPDATE Parent error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  error = 1;
+	  goto stop;
+      }
+
+    if (journal_off)
+      {
+	  /* disabling the Journal File */
+	  ret =
+	      sqlite3_exec (db_handle, "PRAGMA journal_mode=OFF", NULL,
+			    NULL, &err_msg);
+	  if (ret != SQLITE_OK)
+	    {
+		fprintf (stderr, "JOURNAL MODE=OFF error: %s\n", err_msg);
+		sqlite3_free (err_msg);
+		goto stop;
+	    }
+	  ret =
+	      sqlite3_exec (db_handle, "PRAGMA synchronous=OFF", NULL,
+			    NULL, &err_msg);
+	  if (ret != SQLITE_OK)
+	    {
+		fprintf (stderr, "SYNCHRONOUS=OFF error: %s\n", err_msg);
+		sqlite3_free (err_msg);
+		goto stop;
+	    }
+      }
+
+/* starting a transaction */
+    ret = sqlite3_exec (db_handle, "BEGIN", NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "BEGIN error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  goto stop;
+      }
+
+    while (1)
+      {
+	  /* scrolling the result set rows */
+	  ret = sqlite3_step (sel_stmt);
+	  if (ret == SQLITE_DONE)
+	      break;		/* end of result set */
+	  if (ret == SQLITE_ROW)
+	    {
+		/* fetching an input row from the Child Table */
+		int main_value_null = 0;
+		pk_value = sqlite3_column_int64 (sel_stmt, 0);
+		if (sqlite3_column_type (sel_stmt, 1) == SQLITE_NULL)
+		    main_value_null = 1;
+		else
+		    main_value = sqlite3_column_text (sel_stmt, 1);
+		reset_attribute_values (list);
+		for (i = 2; i < sqlite3_column_count (sel_stmt); i++)
+		  {
+		      const char *name = sqlite3_column_name (sel_stmt, i);
+		      switch (sqlite3_column_type (sel_stmt, i))
+			{
+			case SQLITE_INTEGER:
+			    set_int_value (list, name,
+					   sqlite3_column_int64 (sel_stmt, i));
+			    break;
+			case SQLITE_FLOAT:
+			    set_double_value (list, name,
+					      sqlite3_column_double (sel_stmt,
+								     i));
+			    break;
+			case SQLITE_TEXT:
+			    set_text_value (list, name,
+					    sqlite3_column_text (sel_stmt, i));
+			    break;
+			case SQLITE_BLOB:
+			    set_blob_value (list, name,
+					    sqlite3_column_blob (sel_stmt, i),
+					    sqlite3_column_bytes (sel_stmt, i));
+			    break;
+			};
+		  }
+		/* updating the Parent Table */
+		sqlite3_reset (upd_stmt);
+		sqlite3_clear_bindings (upd_stmt);
+		if (main_value_null)
+		    sqlite3_bind_null (upd_stmt, 1);
+		else
+		    sqlite3_bind_text (upd_stmt, 1, (const char *) main_value,
+				       strlen ((const char *) main_value),
+				       SQLITE_STATIC);
+		i = 2;
+		attr = list->first;
+		while (attr != NULL)
+		  {
+		      if (attr->main_collapsed)
+			{
+			    /* skipping the "main" attribute (child tag name) */
+			    attr = attr->next;
+			    continue;
+			}
+		      switch (attr->datatype)
+			{
+			case SQLITE_INTEGER:
+			    sqlite3_bind_int64 (upd_stmt, i, attr->int_value);
+			    break;
+			case SQLITE_FLOAT:
+			    sqlite3_bind_double (upd_stmt, i,
+						 attr->double_value);
+			    break;
+			case SQLITE_TEXT:
+			    sqlite3_bind_text (upd_stmt, i,
+					       (const char
+						*) (attr->text_value),
+					       strlen ((const char
+							*) (attr->text_value)),
+					       SQLITE_STATIC);
+			    break;
+			case SQLITE_BLOB:
+			    sqlite3_bind_blob (upd_stmt, i, attr->blob_value,
+					       attr->blob_size, SQLITE_STATIC);
+			    break;
+			default:
+			    sqlite3_bind_null (upd_stmt, i);
+			    break;
+			};
+		      i++;
+		      attr = attr->next;
+		  }
+		sqlite3_bind_int64 (upd_stmt, i, pk_value);
+		/* UPDATing */
+		ret = sqlite3_step (upd_stmt);
+		if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+		    ;
+		else
+		  {
+		      fprintf (stderr, "sqlite3_step [WRITE] error: %s\n",
+			       sqlite3_errmsg (db_handle));
+		      error = 1;
+		      goto stop;
+		  }
+	    }
+	  else
+	    {
+		fprintf (stderr, "sqlite3_step [READ] error: %s\n",
+			 sqlite3_errmsg (db_handle));
+		error = 1;
+		goto stop;
+	    }
+      }
+
+/* finally dropping the Child Table */
+    sql = sqlite3_mprintf ("DROP TABLE \"%s\"", table);
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "DROP TABLE error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  error = 1;
+	  goto stop;
+      }
+
+/* updating xml_metacatalog_tables (child) */
+    sql = sqlite3_mprintf ("UPDATE xml_metacatalog_tables "
+			   "SET status = 'post-processed: collapsed and then dropped' "
+			   "WHERE table_name = %Q", tbl->table_name);
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "UPDATE xml_metacatalog_tables (child): %s\n",
+		   err_msg);
+	  sqlite3_free (err_msg);
+      }
+
+/* updating xml_metacatalog_tables (parent) */
+    sql = sqlite3_mprintf ("UPDATE xml_metacatalog_tables "
+			   "SET status = 'post-processed: receiving collapsed children' "
+			   "WHERE table_name = %Q", tbl->parent_table);
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "UPDATE xml_metacatalog_tables (parent): %s\n",
+		   err_msg);
+	  sqlite3_free (err_msg);
+      }
+
+    attr = list->first;
+    while (attr != NULL)
+      {
+	  /* updating xml_metacatalog_columns (parent) */
+	  char *xml;
+	  char *parent_tag;
+	  char *geom = NULL;
+	  if (tbl->parent->tag_ns == NULL)
+	      parent_tag = sqlite3_mprintf ("<%s>", tbl->parent->tag_name);
+	  else
+	      parent_tag =
+		  sqlite3_mprintf ("<%s:%s>", tbl->parent->tag_ns,
+				   tbl->parent->tag_name);
+	  xml =
+	      sqlite3_mprintf ("%s%s%s", parent_tag, attr->xml_reference,
+			       parent_tag);
+	  sqlite3_free (parent_tag);
+	  if (tbl->geometry != NULL)
+	    {
+		if (strcmp (attr->attr_name, tbl->geometry) == 0)
+		    geom =
+			sqlite3_mprintf ("GeomFromGml(\"%s\")", tbl->tag_name);
+	    }
+	  if (geom != NULL)
+	    {
+		sql = sqlite3_mprintf ("INSERT INTO xml_metacatalog_columns "
+				       "(table_name, column_name, origin, destination, xml_reference) VALUES "
+				       "(%Q, %Q, %Q, NULL, %Q)",
+				       tbl->parent_table, attr->attr_name, geom,
+				       xml);
+		sqlite3_free (geom);
+	    }
+	  else
+	      sql = sqlite3_mprintf ("INSERT INTO xml_metacatalog_columns "
+				     "(table_name, column_name, origin, destination, xml_reference) VALUES "
+				     "(%Q, %Q, %Q, NULL, %Q)",
+				     tbl->parent_table, attr->attr_name,
+				     "collapsed from child node", xml);
+	  sqlite3_free (xml);
+	  ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+	  sqlite3_free (sql);
+	  if (ret != SQLITE_OK)
+	    {
+		fprintf (stderr, "INSERT INTO xml_metacatalog_columns: %s\n",
+			 err_msg);
+		sqlite3_free (err_msg);
+	    }
+	  /* updating xml_metacatalog_columns (child) */
+	  xml =
+	      sqlite3_mprintf ("collapsed into \"%s\".\"%s\"",
+			       tbl->parent_table, attr->attr_name);
+	  sql =
+	      sqlite3_mprintf
+	      ("UPDATE xml_metacatalog_columns SET destination = %Q "
+	       "WHERE table_name = %Q AND column_name = %Q", xml,
+	       tbl->table_name, attr->attr_name);
+	  sqlite3_free (xml);
+	  ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+	  sqlite3_free (sql);
+	  if (ret != SQLITE_OK)
+	    {
+		fprintf (stderr, "UPDATE xml_metacatalog_columns: %s\n",
+			 err_msg);
+		sqlite3_free (err_msg);
+	    }
+	  attr = attr->next;
+      }
+
+/* committing the transaction */
+    ret = sqlite3_exec (db_handle, "COMMIT", NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "COMMIT error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+      }
+
+  stop:
+    if (sel_stmt != NULL)
+	sqlite3_finalize (sel_stmt);
+    if (upd_stmt != NULL)
+	sqlite3_finalize (upd_stmt);
+    if (error)
+	return 0;
+    return 1;
+}
+
+static void
+get_xml_references (sqlite3 * db_handle, struct new_attributes *list,
+		    const char *table)
+{
+/* fetching the xml_references for any column to be collapsed */
+    struct xml_attribute *attr = list->first;
+    while (attr != NULL)
+      {
+	  int ret;
+	  char *err_msg = NULL;
+	  char **results;
+	  int rows;
+	  int columns;
+	  int i;
+	  int len;
+	  const char *name;
+	  char *sql;
+	  if (attr->main_collapsed)
+	      sql = sqlite3_mprintf ("SELECT xml_reference "
+				     "FROM xml_metacatalog_columns "
+				     "WHERE table_name = %Q AND column_name = %Q",
+				     table, "node_value");
+	  else
+	      sql = sqlite3_mprintf ("SELECT xml_reference "
+				     "FROM xml_metacatalog_columns "
+				     "WHERE table_name = %Q AND column_name = %Q",
+				     table, attr->attr_name);
+	  ret =
+	      sqlite3_get_table (db_handle, sql, &results, &rows, &columns,
+				 NULL);
+	  sqlite3_free (sql);
+	  if (ret != SQLITE_OK)
+	    {
+		fprintf (stderr, "SELECT xml_referemce error: %s\n", err_msg);
+		sqlite3_free (err_msg);
+		goto default_ref;
+	    }
+	  if (rows < 1)
+	    {
+		sqlite3_free_table (results);
+		goto default_ref;
+	    }
+	  for (i = 1; i <= rows; i++)
+	    {
+		name = results[(i * columns) + 0];
+		if (attr->xml_reference != NULL)
+		    free (attr->xml_reference);
+		len = strlen (name);
+		attr->xml_reference = malloc (len + 1);
+		strcpy (attr->xml_reference, name);
+	    }
+	  sqlite3_free_table (results);
+	  attr = attr->next;
+	  continue;
+	default_ref:
+	  name = "?unknown?";
+	  if (attr->xml_reference != NULL)
+	      free (attr->xml_reference);
+	  len = strlen (name);
+	  attr->xml_reference = malloc (len + 1);
+	  strcpy (attr->xml_reference, name);
+	  attr = attr->next;
+      }
+}
+
+static int
+test_index (sqlite3 * db_handle, const char *table, const char *column)
+{
+/* tests if an index exists */
+    int ret;
+    char *err_msg = NULL;
+    char **results;
+    int rows;
+    int columns;
+    int i;
+    int ok = 0;
+
+/* checking the expected columns */
+    char *idx = sqlite3_mprintf ("idx_%s_%s", table, column);
+    char *sql = sqlite3_mprintf ("SELECT name FROM sqlite_master "
+				 "WHERE type = 'index' AND tbl_name = %Q AND name = %Q",
+				 table, idx);
+    sqlite3_free (idx);
+    ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SELECT FROM sqlite_master error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+    if (rows < 1)
+	;
+    else
+      {
+	  for (i = 1; i <= rows; i++)
+	      ok = 1;
+      }
+    sqlite3_free_table (results);
+    return ok;
+}
+
+static struct new_attributes *
+upgrade_parent (sqlite3 * db_handle, const char *table, const char *parent,
+		const char *attr_name, const char *geometry_name)
+{
+/* attempting to upgrade the parent table */
+    int ret;
+    char *err_msg = NULL;
+    char **results;
+    int rows;
+    int columns;
+    int i;
+    int error = 0;
+    struct new_attributes *list = alloc_new_attributes ();
+    char *sql;
+    struct xml_attribute *attr;
+
+/* inserting the tag name itself */
+    add_attribute (list, attr_name, 1);
+
+/* extracting the column (XML Attributes) names from the Child Table */
+    sql = sqlite3_mprintf ("PRAGMA table_info(\"%s\")", table);
+    ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "PRAGMA table_info[Child] error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  goto done;
+      }
+    if (rows < 1)
+	;
+    else
+      {
+	  for (i = 1; i <= rows; i++)
+	    {
+		const char *name = results[(i * columns) + 1];
+		if (strcmp (name, "node_id") == 0)
+		    continue;
+		if (strcmp (name, "parent_id") == 0)
+		    continue;
+		if (strcmp (name, "node_value") == 0)
+		    continue;
+		add_attribute (list, name, 0);
+	    }
+      }
+    sqlite3_free_table (results);
+
+/* extracting the column (XML Attributes) names from the Parent Table */
+    sql = sqlite3_mprintf ("PRAGMA table_info(\"%s\")", parent);
+    ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "PRAGMA table_info[Parent] error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  goto done;
+      }
+    if (rows < 1)
+	;
+    else
+      {
+	  for (i = 1; i <= rows; i++)
+	    {
+		const char *name = results[(i * columns) + 1];
+		check_attribute (list, name);
+	    }
+      }
+    sqlite3_free_table (results);
+
+    if (list->collision)
+      {
+	  error = 1;
+	  goto done;
+      }
+
+    attr = list->first;
+    while (attr != NULL)
+      {
+	  /* adding the new Columns to the Parent Table */
+	  const char *type = "TEXT";
+	  if (geometry_name != NULL)
+	    {
+		if (strcmp (geometry_name, attr->attr_name) == 0)
+		    type = "BLOB";
+	    }
+	  sql =
+	      sqlite3_mprintf ("ALTER TABLE \"%s\" ADD COLUMN \"%s\" %s",
+			       parent, attr->attr_name, type);
+	  ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+	  sqlite3_free (sql);
+	  if (ret != SQLITE_OK)
+	    {
+		fprintf (stderr, "ALTER TABLE error: %s\n", err_msg);
+		sqlite3_free (err_msg);
+		error = 1;
+		goto done;
+	    }
+	  attr = attr->next;
+      }
+
+    attr = list->first;
+    while (attr != NULL)
+      {
+	  if (strcmp (attr->attr_name, "gml_id") == 0)
+	    {
+		if (test_index (db_handle, table, "gml_id"))
+		  {
+		      /* creating an Index supporting "gml_id" */
+		      sql = sqlite3_mprintf ("CREATE INDEX IF NOT EXISTS "
+					     "\"idx_%s_gml_id\" ON \"%s\" (gml_id)",
+					     parent, parent);
+		      ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+		      sqlite3_free (sql);
+		      if (ret != SQLITE_OK)
+			{
+			    fprintf (stderr,
+				     "CREATE INDEX [gml_id] error: %s\n",
+				     err_msg);
+			    sqlite3_free (err_msg);
+			    error = 1;
+			    goto done;
+			}
+		  }
+	    }
+	  if (strcmp (attr->attr_name, "xlink_href") == 0)
+	    {
+		if (test_index (db_handle, table, "xlink_href"))
+		  {
+		      /* creating an Index supporting "xlink_href" */
+		      sql = sqlite3_mprintf ("CREATE INDEX IF NOT EXISTS "
+					     "\"idx_%s_xlink_href\" ON \"%s\" (xlink_href)",
+					     parent, parent);
+		      ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+		      sqlite3_free (sql);
+		      if (ret != SQLITE_OK)
+			{
+			    fprintf (stderr,
+				     "CREATE INDEX [xlink_href] error: %s\n",
+				     err_msg);
+			    sqlite3_free (err_msg);
+			    error = 1;
+			    goto done;
+			}
+		  }
+	    }
+	  attr = attr->next;
+      }
+
+  done:
+    if (error)
+      {
+	  destroy_new_attributes (list);
+	  return NULL;
+      }
+    return list;
+}
+
+static int
+check_collapsible (sqlite3 * db_handle, const char *table, const char *parent)
+{
+/* tests if this table could be collapsed as an XML parent Attribute */
+    char *sql;
+    int ret;
+    char *err_msg = NULL;
+    int multi = 0;
+    sqlite3_stmt *stmt;
+
+    sql = sqlite3_mprintf ("SELECT p.node_id, Count(*) AS cnt "
+			   "FROM \"%s\" AS c JOIN \"%s\" AS p ON (p.node_id = c.parent_id) "
+			   "GROUP BY p.node_id HAVING cnt > 1", table, parent);
+    ret = sqlite3_prepare_v2 (db_handle, sql, strlen (sql), &stmt, NULL);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SELECT multi-values: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+    while (1)
+      {
+	  /* scrolling the result set rows */
+	  ret = sqlite3_step (stmt);
+	  if (ret == SQLITE_DONE)
+	      break;		/* end of result set */
+	  if (ret == SQLITE_ROW)
+	      multi++;
+      }
+    sqlite3_finalize (stmt);
+    if (multi > 0)
+	return 0;
+
+    return 1;
+}
+
+static char *
+check_xml_child_table (sqlite3 * db_handle, const char *table)
+{
+/* tests if this table seems to be an XML child table */
+    int ret;
+    char *err_msg = NULL;
+    char **results;
+    int rows;
+    int columns;
+    int i;
+    int ok_pk = 0;
+    int ok_fk = 0;
+    int ok_value = 0;
+    int error = 0;
+    char *parent = NULL;
+    int fk = 0;
+
+/* checking the expected columns */
+    char *sql = sqlite3_mprintf ("PRAGMA table_info(\"%s\")", table);
+    ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "PRAGMA table_info error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  return NULL;
+      }
+    if (rows < 1)
+	;
+    else
+      {
+	  for (i = 1; i <= rows; i++)
+	    {
+		const char *name = results[(i * columns) + 1];
+		if (strcmp (name, "node_id") == 0)
+		  {
+		      if (atoi (results[(i * columns) + 5]) == 1)
+			  ok_pk = 1;
+		  }
+		else if (atoi (results[(i * columns) + 5]) == 1)
+		    error = 1;
+		if (strcmp (name, "parent_id") == 0)
+		    ok_fk = 1;
+		if (strcmp (name, "node_value") == 0)
+		    ok_value = 1;
+	    }
+      }
+    sqlite3_free_table (results);
+    if (error)
+	return NULL;
+    if (ok_pk == 0)
+	return NULL;
+    if (ok_fk == 0)
+	return NULL;
+    if (ok_value == 0)
+	return NULL;
+
+/* checking the Foreing Key */
+    sql = sqlite3_mprintf ("PRAGMA foreign_key_list(\"%s\")", table);
+    ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "PRAGMA foreign_key_list error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  return NULL;
+      }
+    if (rows < 1)
+	;
+    else
+      {
+	  for (i = 1; i <= rows; i++)
+	    {
+		int len;
+		const char *name = results[(i * columns) + 2];
+		if (parent != NULL)
+		    free (parent);
+		len = strlen (name);
+		parent = malloc (len + 1);
+		strcpy (parent, name);
+		fk++;
+		if (strcmp (results[(i * columns) + 3], "parent_id") != 0
+		    || strcmp (results[(i * columns) + 4], "node_id") != 0)
+		    error = 1;
+	    }
+      }
+    sqlite3_free_table (results);
+    if (error || fk != 1)
+      {
+	  if (parent != NULL)
+	      free (parent);
+	  return NULL;
+      }
+
+    return parent;
+}
+
+static void
+spatialite_autocreate (sqlite3 * db)
+{
+/* attempting to perform self-initialization for a newly created DB */
+    int ret;
+    char sql[1024];
+    char *err_msg = NULL;
+    int count;
+    int i;
+    char **results;
+    int rows;
+    int columns;
+
+/* checking if this DB is really empty */
+    strcpy (sql, "SELECT Count(*) from sqlite_master");
+    ret = sqlite3_get_table (db, sql, &results, &rows, &columns, NULL);
+    if (ret != SQLITE_OK)
+	return;
+    if (rows < 1)
+	;
+    else
+      {
+	  for (i = 1; i <= rows; i++)
+	      count = atoi (results[(i * columns) + 0]);
+      }
+    sqlite3_free_table (results);
+
+    if (count > 0)
+	return;
+
+/* all right, it's empty: proceding to initialize */
+    strcpy (sql, "SELECT InitSpatialMetadata(1)");
+    ret = sqlite3_exec (db, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "InitSpatialMetadata() error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  return;
+      }
+}
+
+static int
+check_xml_metacatalog (sqlite3 * db_handle)
+{
+/* checking if XML-metacatalog tables do really exist */
+    int ret;
+    const char *sql;
+    char *err_msg = NULL;
+    char **results;
+    int rows;
+    int columns;
+    int i;
+    int ok_table_name = 0;
+    int ok_tree_level = 0;
+    int ok_xml_tag_namespace = 0;
+    int ok_xml_tag_name = 0;
+    int ok_parent_table_name = 0;
+    int ok_gml_geometry_column = 0;
+    int ok_status = 0;
+    int ok_column_name = 0;
+    int ok_origin = 0;
+    int ok_destination = 0;
+    int ok_xml_reference = 0;
+    int error = 0;
+
+/* checking xml_metacatalog_tables */
+    sql = "PRAGMA table_info(xml_metacatalog_tables)";
+    ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "PRAGMA xml_metacatalog_tables error: %s\n",
+		   err_msg);
+	  sqlite3_free (err_msg);
+	  goto done;
+      }
+    if (rows < 1)
+	;
+    else
+      {
+	  for (i = 1; i <= rows; i++)
+	    {
+		const char *name = results[(i * columns) + 1];
+		if (strcmp (name, "table_name") == 0)
+		    ok_table_name = 1;
+		if (strcmp (name, "tree_level") == 0)
+		    ok_tree_level = 1;
+		if (strcmp (name, "xml_tag_namespace") == 0)
+		    ok_xml_tag_namespace = 1;
+		if (strcmp (name, "xml_tag_name") == 0)
+		    ok_xml_tag_name = 1;
+		if (strcmp (name, "parent_table_name") == 0)
+		    ok_parent_table_name = 1;
+		if (strcmp (name, "gml_geometry_column") == 0)
+		    ok_gml_geometry_column = 1;
+		if (strcmp (name, "status") == 0)
+		    ok_status = 1;
+	    }
+      }
+    sqlite3_free_table (results);
+    if (ok_table_name && ok_tree_level && ok_xml_tag_namespace
+	&& ok_xml_tag_name && ok_parent_table_name && ok_gml_geometry_column
+	&& ok_status)
+	;
+    else
+      {
+	  error = 1;
+	  goto done;
+      }
+    ok_table_name = 0;
+
+/* checking xml_metacatalog_columns */
+    sql = "PRAGMA table_info(xml_metacatalog_columns)";
+    ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "PRAGMA xml_metacatalog_columns error: %s\n",
+		   err_msg);
+	  sqlite3_free (err_msg);
+	  goto done;
+      }
+    if (rows < 1)
+	;
+    else
+      {
+	  for (i = 1; i <= rows; i++)
+	    {
+		const char *name = results[(i * columns) + 1];
+		if (strcmp (name, "table_name") == 0)
+		    ok_table_name = 1;
+		if (strcmp (name, "column_name") == 0)
+		    ok_column_name = 1;
+		if (strcmp (name, "origin") == 0)
+		    ok_origin = 1;
+		if (strcmp (name, "destination") == 0)
+		    ok_destination = 1;
+		if (strcmp (name, "xml_reference") == 0)
+		    ok_xml_reference = 1;
+	    }
+      }
+    sqlite3_free_table (results);
+    if (ok_table_name && ok_column_name && ok_origin && ok_destination
+	&& ok_xml_reference)
+	;
+    else
+      {
+	  error = 1;
+	  goto done;
+      }
+
+  done:
+    if (error)
+	return 0;
+    return 1;
+}
+
+static void
+open_db (const char *path, sqlite3 ** handle, int cache_size, void *cache)
+{
+/* opening the DB */
+    sqlite3 *db_handle;
+    int ret;
+    char sql[1024];
+
+    *handle = NULL;
+    printf ("SQLite version: %s\n", sqlite3_libversion ());
+    printf ("SpatiaLite version: %s\n\n", spatialite_version ());
+
+    ret =
+	sqlite3_open_v2 (path, &db_handle,
+			 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "cannot open '%s': %s\n", path,
+		   sqlite3_errmsg (db_handle));
+	  sqlite3_close (db_handle);
+	  db_handle = NULL;
+	  return;
+      }
+
+    if (!check_xml_metacatalog (db_handle))
+      {
+	  fprintf (stderr,
+		   "XML-metacatalog not found or invalid ... cowardly quitting\n");
+	  sqlite3_close (db_handle);
+	  return;
+      }
+
+    spatialite_init_ex (db_handle, cache, 0);
+    spatialite_autocreate (db_handle);
+
+    if (cache_size > 0)
+      {
+	  /* setting the CACHE-SIZE */
+	  sprintf (sql, "PRAGMA cache_size=%d", cache_size);
+	  sqlite3_exec (db_handle, sql, NULL, NULL, NULL);
+      }
+
+/* enabling PK/FK constraints */
+    sqlite3_exec (db_handle, "PRAGMA foreign_keys = 1", NULL, NULL, NULL);
+    *handle = db_handle;
+    return;
+}
+
+static void
+do_help ()
+{
+/* printing the argument list */
+    fprintf (stderr, "\n\nusage: spatialite_xml_collapse ARGLIST\n");
+    fprintf (stderr,
+	     "==============================================================\n");
+    fprintf (stderr,
+	     "-h or --help                    print this help message\n");
+    fprintf (stderr,
+	     "-d or --db-path     pathname    the SpatiaLite DB path\n\n");
+    fprintf (stderr, "you can specify the following options as well\n");
+    fprintf (stderr,
+	     "-dd or --delete-duplicates      remove all duplicate rows except one\n");
+    fprintf (stderr,
+	     "-nl or --nl-level      num      tree-level for table-names (dft: 0)\n\n");
+    fprintf (stderr,
+	     "-jo or --journal-off            unsafe [but faster] mode\n");
+    fprintf (stderr,
+	     "-cs or --cache-size    num      DB cache size (how many pages)\n");
+    fprintf (stderr,
+	     "-m or --in-memory               using IN-MEMORY database\n");
+}
+
+int
+main (int argc, char *argv[])
+{
+/* the MAIN function mainly perform arguments checking */
+    sqlite3 *handle;
+    char *err_msg = NULL;
+    int ret;
+    int i;
+    int error = 0;
+    int next_arg = ARG_NONE;
+    const char *db_path = NULL;
+    int delete_duplicates = 0;
+    int name_level = -1;
+    int in_memory = 0;
+    int cache_size = 0;
+    int journal_off = 0;
+    void *cache;
+    const char *sql;
+    char **results;
+    int rows;
+    int columns;
+    int loop_again = 1;
+    struct xml_geometry *geom;
+    struct xml_tables_list *catalog = alloc_xml_tables ();
+
+    for (i = 1; i < argc; i++)
+      {
+	  /* parsing the invocation arguments */
+	  if (next_arg != ARG_NONE)
+	    {
+		switch (next_arg)
+		  {
+		  case ARG_DB_PATH:
+		      db_path = argv[i];
+		      break;
+		  case ARG_CACHE_SIZE:
+		      cache_size = atoi (argv[i]);
+		      break;
+		  case ARG_NAME_LEVEL:
+		      name_level = atoi (argv[i]);
+		      break;
+		  };
+		next_arg = ARG_NONE;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "--help") == 0
+	      || strcmp (argv[i], "-h") == 0)
+	    {
+		do_help ();
+		return -1;
+	    }
+	  if (strcmp (argv[i], "-d") == 0)
+	    {
+		next_arg = ARG_DB_PATH;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "--db-path") == 0)
+	    {
+		next_arg = ARG_DB_PATH;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "--cache-size") == 0
+	      || strcmp (argv[i], "-cs") == 0)
+	    {
+		next_arg = ARG_CACHE_SIZE;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "--name-level") == 0
+	      || strcmp (argv[i], "-nl") == 0)
+	    {
+		next_arg = ARG_NAME_LEVEL;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "-jo") == 0)
+	    {
+		journal_off = 1;
+		next_arg = ARG_NONE;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "--journal-off") == 0)
+	    {
+		journal_off = 1;
+		next_arg = ARG_NONE;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "-m") == 0)
+	    {
+		in_memory = 1;
+		next_arg = ARG_NONE;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "--in-memory") == 0)
+	    {
+		in_memory = 1;
+		next_arg = ARG_NONE;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "-dd") == 0)
+	    {
+		delete_duplicates = 1;
+		next_arg = ARG_NONE;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "--delete-duplicates") == 0)
+	    {
+		delete_duplicates = 1;
+		next_arg = ARG_NONE;
+		continue;
+	    }
+	  fprintf (stderr, "unknown argument: %s\n", argv[i]);
+	  error = 1;
+      }
+    if (error)
+      {
+	  do_help ();
+	  return -1;
+      }
+
+/* checking the arguments */
+    if (!db_path)
+      {
+	  fprintf (stderr, "did you forget setting the --db-path argument ?\n");
+	  error = 1;
+      }
+    if (delete_duplicates && name_level < 0)
+      {
+	  fprintf (stderr, "--delete-duplicates requires --name-level\n");
+	  error = 1;
+      }
+    if (error)
+      {
+	  do_help ();
+	  return -1;
+      }
+
+/* opening the DB */
+    if (in_memory)
+	cache_size = 0;
+    cache = spatialite_alloc_connection ();
+    open_db (db_path, &handle, cache_size, cache);
+    if (!handle)
+	return -1;
+
+    if (in_memory)
+      {
+	  /* loading the DB in-memory */
+	  sqlite3 *mem_db_handle;
+	  sqlite3_backup *backup;
+	  int ret;
+	  ret =
+	      sqlite3_open_v2 (":memory:", &mem_db_handle,
+			       SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
+			       NULL);
+	  if (ret != SQLITE_OK)
+	    {
+		fprintf (stderr, "cannot open 'MEMORY-DB': %s\n",
+			 sqlite3_errmsg (mem_db_handle));
+		sqlite3_close (mem_db_handle);
+		return -1;
+	    }
+	  backup = sqlite3_backup_init (mem_db_handle, "main", handle, "main");
+	  if (!backup)
+	    {
+		fprintf (stderr, "cannot load 'MEMORY-DB'\n");
+		sqlite3_close (handle);
+		sqlite3_close (mem_db_handle);
+		return -1;
+	    }
+	  while (1)
+	    {
+		ret = sqlite3_backup_step (backup, 1024);
+		if (ret == SQLITE_DONE)
+		    break;
+	    }
+	  ret = sqlite3_backup_finish (backup);
+	  sqlite3_close (handle);
+	  handle = mem_db_handle;
+	  printf ("\nusing IN-MEMORY database\n");
+	  spatialite_cleanup_ex (cache);
+	  cache = spatialite_alloc_connection ();
+	  spatialite_init_ex (handle, cache, 0);
+      }
+
+/* identifying the tables to be (possibly) collapsed */
+    sql =
+	"SELECT table_name, parent_table_name, xml_tag_namespace, xml_tag_name, "
+	"gml_geometry_column, tree_level FROM xml_metacatalog_tables "
+	"WHERE status LIKE 'raw %'";
+    ret = sqlite3_get_table (handle, sql, &results, &rows, &columns, NULL);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SELECT FROM xml_metacatalog_tables error: %s\n",
+		   err_msg);
+	  sqlite3_free (err_msg);
+	  goto abort;
+      }
+    if (rows < 1)
+	;
+    else
+      {
+	  for (i = 1; i <= rows; i++)
+	    {
+		const char *table = results[(i * columns) + 0];
+		const char *parent = results[(i * columns) + 1];
+		const char *tag_ns = results[(i * columns) + 2];
+		const char *tag_name = results[(i * columns) + 3];
+		const char *geometry = results[(i * columns) + 4];
+		int level = atoi (results[(i * columns) + 5]);
+		add_xml_table (catalog, table, parent, tag_ns, tag_name,
+			       geometry, level);
+	    }
+      }
+    sqlite3_free_table (results);
+
+    identify_childs (catalog);
+    while (loop_again)
+      {
+	  /* iteratively attempting to collapse */
+	  struct xml_table *tbl = catalog->first;
+	  loop_again = 0;
+	  while (tbl != NULL)
+	    {
+		if (tbl->first == NULL && tbl->done == 0)
+		  {
+		      char *parent =
+			  check_xml_child_table (handle, tbl->table_name);
+		      loop_again = 1;
+		      tbl->done = 1;
+		      if (parent != NULL)
+			{
+			    if (check_collapsible
+				(handle, tbl->table_name, parent))
+			      {
+				  struct new_attributes *list =
+				      upgrade_parent (handle, tbl->table_name,
+						      parent, tbl->tag_name,
+						      tbl->geometry);
+				  if (list != NULL)
+				    {
+					get_xml_references (handle, list,
+							    tbl->table_name);
+					ret =
+					    collapse_table (handle, journal_off,
+							    list,
+							    tbl->table_name,
+							    parent, tbl);
+					destroy_new_attributes (list);
+					if (!ret)
+					  {
+					      fprintf (stderr,
+						       "Unable to collapse \"%s\"\n",
+						       tbl->table_name);
+					      free (parent);
+					      goto abort;
+					  }
+				    }
+			      }
+			    free (parent);
+			}
+		  }
+		tbl = tbl->next;
+	    }
+      }
+
+    if (delete_duplicates)
+      {
+	  /* deleting duplicates */
+	  struct xml_table *tbl = catalog->first;
+	  while (tbl != NULL)
+	    {
+		if (tbl->level == name_level)
+		    remove_duplicates (handle, tbl);
+		tbl = tbl->next;
+	    }
+      }
+
+/* identifying the Geometries to be (possibly) recovered */
+    sql =
+	"SELECT table_name, column_name FROM xml_metacatalog_columns "
+	"WHERE origin LIKE 'GeomFromGml%'";
+    ret = sqlite3_get_table (handle, sql, &results, &rows, &columns, NULL);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SELECT FROM xml_metacatalog_columns error: %s\n",
+		   err_msg);
+	  sqlite3_free (err_msg);
+	  goto abort;
+      }
+    if (rows < 1)
+	;
+    else
+      {
+	  for (i = 1; i <= rows; i++)
+	    {
+		const char *table = results[(i * columns) + 0];
+		const char *geometry = results[(i * columns) + 1];
+		add_xml_geometry (catalog, table, geometry);
+	    }
+      }
+    sqlite3_free_table (results);
+
+    geom = catalog->first_geom;
+    while (geom != NULL)
+      {
+	  check_geometry (handle, geom);
+	  if (geom->type != NULL)
+	      recover_geometry (handle, geom);
+	  geom = geom->next;
+      }
+
+  abort:
+    destroy_xml_tables (catalog);
+
+    if (in_memory)
+      {
+	  /* exporting the in-memory DB to filesystem */
+	  sqlite3 *disk_db_handle;
+	  sqlite3_backup *backup;
+	  int ret;
+	  printf ("\nexporting IN_MEMORY database ... wait please ...\n");
+	  ret =
+	      sqlite3_open_v2 (db_path, &disk_db_handle,
+			       SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
+			       NULL);
+	  if (ret != SQLITE_OK)
+	    {
+		fprintf (stderr, "cannot open '%s': %s\n", db_path,
+			 sqlite3_errmsg (disk_db_handle));
+		sqlite3_close (disk_db_handle);
+		return -1;
+	    }
+	  backup = sqlite3_backup_init (disk_db_handle, "main", handle, "main");
+	  if (!backup)
+	    {
+		fprintf (stderr, "Backup failure: 'MEMORY-DB' wasn't saved\n");
+		sqlite3_close (handle);
+		sqlite3_close (disk_db_handle);
+		return -1;
+	    }
+	  while (1)
+	    {
+		ret = sqlite3_backup_step (backup, 1024);
+		if (ret == SQLITE_DONE)
+		    break;
+	    }
+	  ret = sqlite3_backup_finish (backup);
+	  sqlite3_close (handle);
+	  handle = disk_db_handle;
+	  printf ("\tIN_MEMORY database succesfully exported\n");
+      }
+    sqlite3_close (handle);
+    spatialite_cleanup_ex (cache);
+    return 0;
+}
diff --git a/spatialite_xml_load.c b/spatialite_xml_load.c
new file mode 100644
index 0000000..247d95a
--- /dev/null
+++ b/spatialite_xml_load.c
@@ -0,0 +1,2837 @@
+/* 
+/ spatialite_xml_load
+/
+/ a tool loading any XML into SQLite tables
+/
+/ version 1.0, 2013 August 14
+/
+/ Author: Sandro Furieri a.furieri at lqt.it
+/
+/ Copyright (C) 2013  Alessandro Furieri
+/
+/    This program is free software: you can redistribute it and/or modify
+/    it under the terms of the GNU General Public License as published by
+/    the Free Software Foundation, either version 3 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 General Public License for more details.
+/
+/    You should have received a copy of the GNU General Public License
+/    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/
+*/
+
+#include <sys/time.h>
+
+#if defined(_WIN32) && !defined(__MINGW32__)
+/* MSVC strictly requires this include [off_t] */
+#include <sys/types.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <libgen.h>
+
+#include <expat.h>
+
+#include "config.h"
+
+#ifdef SPATIALITE_AMALGAMATION
+#include <spatialite/sqlite3.h>
+#else
+#include <sqlite3.h>
+#endif
+#include <spatialite.h>
+
+#define BUFFSIZE	8192
+
+#define ARG_NONE	0
+#define ARG_XML_PATH	1
+#define ARG_DB_PATH	2
+#define ARG_NAME_LEVEL 3
+#define ARG_PARENT_LEVELS	4
+#define ARG_CACHE_SIZE 5
+
+struct gmlDynBuffer
+{
+/* a struct handling a dynamically growing output buffer */
+    char *Buffer;
+    size_t WriteOffset;
+    size_t BufferSize;
+    int Error;
+};
+
+struct sql_table
+{
+/* a SQL table name */
+    char *table_name;
+    char *parent_table;
+    struct xml_tag *tag;
+    sqlite3_stmt *ins_stmt;
+    sqlite3_stmt *upd_stmt;
+    sqlite3_int64 current;
+    struct sql_table *next;
+};
+
+struct xml_attr
+{
+/* an XML attribute <tag attr="value"> */
+    char *attr_ns;
+    char *attr_name;
+    char *attr_value;
+    int exists;
+    struct xml_attr *next;
+};
+
+struct xml_tag
+{
+/* an XML node <tag name> */
+    char *tag_ns;
+    char *tag_name;
+    char *full_name;
+    char *unique_name;
+    int unique_level;
+    int has_geometry;
+    int tree_level;
+    struct xml_attr *first_attr;
+    struct xml_attr *last_attr;
+    struct xml_tag *parent;
+    struct sql_table *table;
+    struct xml_tag *next;
+};
+
+struct stack_entry
+{
+/* an entry into the tag stack */
+    char *tag_ns;
+    char *tag_name;
+    struct stack_entry *prev;
+};
+
+struct xml_params
+{
+/* an auxiliary struct used for GML parsing */
+    char *filename;
+    sqlite3 *db_handle;
+    int journal_off;
+    int collapsed_gml;
+    int xlink_href;
+    char *CharData;
+    int CharDataLen;
+    int CharDataMax;
+    int CharDataStep;
+    int parse_error;
+    int db_error;
+    struct xml_tag *first_tag;
+    struct xml_tag *last_tag;
+    struct xml_tag **sort_array;
+    int count_array;
+    struct sql_table *first_table;
+    struct sql_table *last_table;
+    struct stack_entry *stack;
+    int CollapsingGML;
+    struct gmlDynBuffer *CollapsedGML;
+    char *CollapsedGMLMarker;
+    int treeLevel;
+};
+
+static struct gmlDynBuffer *
+gmlDynBufferAlloc (void)
+{
+/* creating and initializing a dynamically growing output buffer */
+    struct gmlDynBuffer *buf = malloc (sizeof (struct gmlDynBuffer));
+    buf->Buffer = NULL;
+    buf->WriteOffset = 0;
+    buf->BufferSize = 0;
+    buf->Error = 0;
+    return buf;
+}
+
+static void
+gmlDynBufferDestroy (struct gmlDynBuffer *buf)
+{
+/* cleaning a dynamically growing output buffer */
+    if (buf == NULL)
+	return;
+    if (buf->Buffer)
+	free (buf->Buffer);
+    free (buf);
+}
+
+static void
+gmlDynBufferAppend (struct gmlDynBuffer *buf, const char *payload, size_t size)
+{
+/* appending into the buffer */
+    size_t free_size = buf->BufferSize - buf->WriteOffset;
+    if (size > free_size)
+      {
+	  /* we must allocate a bigger buffer */
+	  size_t new_size;
+	  char *new_buf;
+	  if (buf->BufferSize == 0)
+	      new_size = size + 1024;
+	  else if (buf->BufferSize <= 4196)
+	      new_size = buf->BufferSize + size + 4196;
+	  else if (buf->BufferSize <= 65536)
+	      new_size = buf->BufferSize + size + 65536;
+	  else
+	      new_size = buf->BufferSize + size + (1024 * 1024);
+	  new_buf = malloc (new_size);
+	  if (!new_buf)
+	    {
+		buf->Error = 1;
+		return;
+	    }
+	  if (buf->Buffer)
+	    {
+		memcpy (new_buf, buf->Buffer, buf->WriteOffset);
+		free (buf->Buffer);
+	    }
+	  buf->Buffer = new_buf;
+	  buf->BufferSize = new_size;
+      }
+    memcpy (buf->Buffer + buf->WriteOffset, payload, size);
+    buf->WriteOffset += size;
+}
+
+static void
+xmlCharData (void *data, const XML_Char * s, int len)
+{
+/* parsing XML char data */
+    struct xml_params *params = (struct xml_params *) data;
+    if ((params->CharDataLen + len) > params->CharDataMax)
+      {
+	  /* we must increase the CharData buffer size */
+	  void *new_buf;
+	  int new_size = params->CharDataMax;
+	  while (new_size < params->CharDataLen + len)
+	      new_size += params->CharDataStep;
+	  new_buf = realloc (params->CharData, new_size);
+	  if (new_buf)
+	    {
+		params->CharData = new_buf;
+		params->CharDataMax = new_size;
+	    }
+      }
+    memcpy (params->CharData + params->CharDataLen, s, len);
+    params->CharDataLen += len;
+}
+
+static int
+valid_char_data (struct xml_params *params)
+{
+/* testing if Char Data are meaningfull */
+    int valid = 0;
+    if (params->CharDataLen > 0)
+      {
+	  int i;
+	  for (i = 0; i < params->CharDataLen; i++)
+	    {
+		if (*(params->CharData + i) == ' ')
+		    continue;
+		if (*(params->CharData + i) == '\t')
+		    continue;
+		if (*(params->CharData + i) == '\r')
+		    continue;
+		if (*(params->CharData + i) == '\n')
+		    continue;
+		valid = 1;
+		break;
+	    }
+      }
+    return valid;
+}
+
+static int
+tag_compare (const void *p1, const void *p2)
+{
+/* comparison function for QSort and BSearch*/
+    int ret;
+    struct xml_tag *tag1 = *((struct xml_tag **) p1);
+    struct xml_tag *tag2 = *((struct xml_tag **) p2);
+    ret = strcmp (tag1->full_name, tag2->full_name);
+    if (ret != 0)
+	return ret;
+    if (tag1->tag_ns == NULL && tag2->tag_ns != NULL)
+	return -1;
+    if (tag1->tag_ns != NULL && tag2->tag_ns == NULL)
+	return 1;
+    if (tag1->tag_ns != NULL && tag2->tag_ns != NULL)
+      {
+	  ret = strcmp (tag1->tag_ns, tag2->tag_ns);
+	  if (ret != 0)
+	      return ret;
+      }
+    return strcmp (tag1->tag_name, tag2->tag_name);
+}
+
+static void
+sort_tag_array (struct xml_params *params)
+{
+/* updating the Sorted Tags Array */
+    int count = 0;
+    struct xml_tag *tag = params->first_tag;
+    while (tag != NULL)
+      {
+	  /* counting how many tags are there */
+	  count++;
+	  tag = tag->next;
+      }
+    if (params->sort_array != NULL)
+	free (params->sort_array);
+/* allocating the array */
+    params->count_array = count;
+    params->sort_array = malloc (sizeof (struct xml_tag **) * count);
+    count = 0;
+    tag = params->first_tag;
+    while (tag != NULL)
+      {
+	  /* inserting the pointers into the array */
+	  *(params->sort_array + count++) = tag;
+	  tag = tag->next;
+      }
+    qsort (params->sort_array, params->count_array, sizeof (struct xml_tag *),
+	   tag_compare);
+}
+
+static struct xml_attr *
+alloc_attr (char *ns, char *name)
+{
+/* allocating and initializing an attribute */
+    struct xml_attr *attr = malloc (sizeof (struct xml_attr));
+    attr->attr_ns = ns;
+    attr->attr_name = name;
+    attr->attr_value = NULL;
+    attr->exists = 0;
+    attr->next = NULL;
+    return attr;
+}
+
+static void
+destroy_attr (struct xml_attr *attr)
+{
+/* memory cleanup - freeing an attribute */
+    if (attr == NULL)
+	return;
+    if (attr->attr_ns != NULL)
+	free (attr->attr_ns);
+    if (attr->attr_name != NULL)
+	free (attr->attr_name);
+    if (attr->attr_value != NULL)
+	free (attr->attr_value);
+    free (attr);
+}
+
+static struct sql_table *
+alloc_table (char *table_name, char *parent_table)
+{
+/* allocating and initializing a SQL Table */
+    int len;
+    int i;
+    struct sql_table *table = malloc (sizeof (struct sql_table));
+    table->table_name = table_name;
+    if (table_name != NULL)
+      {
+	  len = strlen (table->table_name);
+	  for (i = 0; i < len; i++)
+	    {
+		char c = *(table->table_name + i);
+		if (c >= 'A' && c <= 'Z')
+		  {
+		      /* forcing to lowercase */
+		      c = c - 'A' + 'a';
+		      *(table->table_name + i) = c;
+		  }
+	    }
+      }
+    table->parent_table = parent_table;
+    if (parent_table != NULL)
+      {
+	  len = strlen (table->parent_table);
+	  for (i = 0; i < len; i++)
+	    {
+		char c = *(table->parent_table + i);
+		if (c >= 'A' && c <= 'Z')
+		  {
+		      /* forcing to lowercase */
+		      c = c - 'A' + 'a';
+		      *(table->parent_table + i) = c;
+		  }
+	    }
+      }
+    table->tag = NULL;
+    table->ins_stmt = NULL;
+    table->upd_stmt = NULL;
+    table->current = 0;
+    table->next = NULL;
+    return table;
+}
+
+static void
+destroy_table (struct sql_table *table)
+{
+/* memory cleanup - freeing a SQL Table */
+    if (table == NULL)
+	return;
+    if (table->ins_stmt != NULL)
+	sqlite3_finalize (table->ins_stmt);
+    if (table->upd_stmt != NULL)
+	sqlite3_finalize (table->upd_stmt);
+    free (table);
+}
+
+static struct xml_tag *
+alloc_tag (const char *tag_ns, const char *tag_name, char *full_name,
+	   struct xml_tag *parent)
+{
+/* allocating and initializing a tag */
+    int len;
+    struct xml_tag *tag = malloc (sizeof (struct xml_tag));
+    if (tag_ns == NULL)
+	tag->tag_ns = NULL;
+    else
+      {
+	  len = strlen (tag_ns);
+	  tag->tag_ns = malloc (len + 1);
+	  strcpy (tag->tag_ns, tag_ns);
+      }
+    len = strlen (tag_name);
+    tag->tag_name = malloc (len + 1);
+    strcpy (tag->tag_name, tag_name);
+    tag->full_name = full_name;
+    tag->unique_name = NULL;
+    tag->first_attr = NULL;
+    tag->last_attr = NULL;
+    tag->parent = parent;
+    tag->unique_level = -1;
+    tag->table = NULL;
+    tag->has_geometry = 0;
+    tag->tree_level = -1;
+    tag->next = NULL;
+    return tag;
+}
+
+static void
+destroy_tag (struct xml_tag *tag)
+{
+/* memory cleanup - freeing a tag */
+    struct xml_attr *pa;
+    struct xml_attr *pan;
+    if (tag == NULL)
+	return;
+    if (tag->tag_ns != NULL)
+	free (tag->tag_ns);
+    if (tag->tag_name != NULL)
+	free (tag->tag_name);
+    if (tag->full_name != NULL)
+	sqlite3_free (tag->full_name);
+    if (tag->unique_name != NULL)
+	sqlite3_free (tag->unique_name);
+    pa = tag->first_attr;
+    while (pa != NULL)
+      {
+	  pan = pa->next;
+	  destroy_attr (pa);
+	  pa = pan;
+      }
+    free (tag);
+}
+
+static void
+reset_tag_attributes (struct xml_tag *tag)
+{
+/* resetting XML attributes to NULL */
+    struct xml_attr *attr = tag->first_attr;
+    while (attr != NULL)
+      {
+	  if (attr->attr_value != NULL)
+	      free (attr->attr_value);
+	  attr->attr_value = NULL;
+	  attr = attr->next;
+      }
+}
+
+static struct xml_tag *
+find_tag (struct xml_params *params, const char *tag_ns, const char *tag_name,
+	  const char *full_name)
+{
+/* attempts to find if some XML Node tag is already defined */
+    struct xml_tag item;
+    struct xml_tag *p_item = &item;
+    struct xml_tag *found;
+    void *x;
+    if (params->sort_array == NULL)
+	return NULL;
+    item.tag_ns = (char *) tag_ns;
+    item.tag_name = (char *) tag_name;
+    item.full_name = (char *) full_name;
+    x = bsearch (&p_item, params->sort_array, params->count_array,
+		 sizeof (struct xml_tag *), tag_compare);
+    if (x == NULL)
+	return NULL;
+    found = *((struct xml_tag **) x);
+    return found;
+}
+
+static struct xml_tag *
+append_tag (struct xml_params *params, const char *tag_ns,
+	    const char *tag_name, char *full_name, struct xml_tag *parent)
+{
+/* appending an XML Node tag */
+    struct xml_tag *tag = alloc_tag (tag_ns, tag_name, full_name, parent);
+    tag->tree_level = params->treeLevel;
+    if (params->first_tag == NULL)
+	params->first_tag = tag;
+    if (params->last_tag != NULL)
+	params->last_tag->next = tag;
+    params->last_tag = tag;
+    sort_tag_array (params);
+    return tag;
+}
+
+static struct xml_attr *
+find_attr (struct xml_tag *tag, const char *ns, const char *name)
+{
+/* attempts to find if some Attribute is already defined */
+    struct xml_attr *p = tag->first_attr;
+    while (p != NULL)
+      {
+	  if (p->attr_ns == NULL && ns == NULL)
+	    {
+		if (strcmp (p->attr_name, name) == 0)
+		    return p;
+	    }
+	  if (p->attr_ns != NULL && ns != NULL)
+	    {
+		if (strcmp (p->attr_ns, ns) == 0
+		    && strcmp (p->attr_name, name) == 0)
+		    return p;
+	    }
+	  p = p->next;
+      }
+    return NULL;
+}
+
+static void
+append_attribute (struct xml_tag *tag, char *ns, char *name)
+{
+/* appending an attribute to an XML Node */
+    struct xml_attr *attr = find_attr (tag, ns, name);
+    if (attr != NULL)
+      {
+	  /* already existing */
+	  if (ns != NULL)
+	      free (ns);
+	  if (name != NULL)
+	      free (name);
+	  return;
+      }
+    attr = alloc_attr (ns, name);
+    if (tag->first_attr == NULL)
+	tag->first_attr = attr;
+    if (tag->last_attr != NULL)
+	tag->last_attr->next = attr;
+    tag->last_attr = attr;
+}
+
+static void
+set_attribute_value (struct xml_tag *tag, const char *ns, const char *name,
+		     const char *value)
+{
+/* setting some value to an Attribute */
+    int len;
+    struct xml_attr *attr = find_attr (tag, ns, name);
+    if (attr == NULL)
+	return;
+    len = strlen (value);
+    if (attr->attr_value != NULL)
+	free (attr->attr_value);
+    attr->attr_value = malloc (len + 1);
+    strcpy (attr->attr_value, value);
+}
+
+static void
+push_stack (struct xml_params *params, char *tag_ns, char *tag_name)
+{
+/* pushing an item into the tag stack */
+    struct stack_entry *entry = malloc (sizeof (struct stack_entry));
+    entry->tag_ns = tag_ns;
+    entry->tag_name = tag_name;
+    entry->prev = params->stack;
+    params->stack = entry;
+}
+
+static void
+pop_stack (struct xml_params *params)
+{
+/* popping an item from the tag stack */
+    struct stack_entry *entry = params->stack;
+    if (entry != NULL)
+      {
+	  params->stack = entry->prev;
+	  if (entry->tag_ns != NULL)
+	      free (entry->tag_ns);
+	  if (entry->tag_name != NULL)
+	      free (entry->tag_name);
+	  free (entry);
+      }
+}
+
+static void
+append_table (struct xml_params *ptr, struct xml_tag *xml, char *table_name,
+	      char *parent_table)
+{
+/* appends a SQL Table definition */
+    struct sql_table *tbl = alloc_table (table_name, parent_table);
+    xml->table = tbl;
+    tbl->tag = xml;
+    if (ptr->first_table == NULL)
+	ptr->first_table = tbl;
+    if (ptr->last_table != NULL)
+	ptr->last_table->next = tbl;
+    ptr->last_table = tbl;
+}
+
+static char *
+build_unique_name (struct xml_tag *tag, int name_level, int parent_levels)
+{
+/* building a qualified tag name */
+    int i;
+    char *str = NULL;
+    struct xml_tag *parent = tag->parent;
+    if (tag->tree_level <= name_level)
+      {
+	  /* above the limit: main branches of the tree -> "child_parent" */
+	  if (parent == NULL)
+	      str = sqlite3_mprintf ("%s", tag->tag_name);
+	  else
+	      str = sqlite3_mprintf ("%s_%s", parent->tag_name, tag->tag_name);
+      }
+    else
+      {
+	  /* under the limit: expanding a full tree branch */
+	  int cnt = 0;
+	  int max = 999999;
+	  if (parent_levels >= 0)
+	      max = parent_levels;
+	  str = sqlite3_mprintf ("%s", tag->tag_name);
+	  for (i = tag->tree_level - 1; i >= name_level; i--)
+	    {
+		char *tmp;
+		if (parent == NULL)
+		  {
+		      sqlite3_free (str);
+		      return NULL;
+		  }
+		if (cnt < max || i == name_level)
+		  {
+		      tmp = sqlite3_mprintf ("%s_%s", parent->tag_name, str);
+		      sqlite3_free (str);
+		      str = tmp;
+		  }
+		cnt++;
+		parent = parent->parent;
+	    }
+      }
+    for (i = 0; i < (int) strlen (str); i++)
+      {
+	  char c = *(str + i);
+	  if (c >= 'A' && c <= 'Z')
+	      *(str + i) = c - 'A' + 'a';
+      }
+    return str;
+}
+
+static void
+set_unique_names (struct xml_params *ptr, int name_level, int parent_levels)
+{
+/* setting the appropriate Unique Names */
+    struct xml_tag *pt = ptr->first_tag;
+    while (pt != NULL)
+      {
+	  char *candidate = build_unique_name (pt, name_level, parent_levels);
+	  if (pt->unique_name != NULL)
+	      sqlite3_free (pt->unique_name);
+	  pt->unique_name = candidate;
+	  pt = pt->next;
+      }
+}
+
+static void
+set_table_names (struct xml_params *ptr)
+{
+/* creating the SQL table names */
+    struct xml_tag *pt = ptr->first_tag;
+    while (pt != NULL)
+      {
+	  struct xml_tag *parent = pt->parent;
+	  char *table_name = pt->unique_name;
+	  char *parent_table = NULL;
+	  if (parent != NULL)
+	      parent_table = parent->unique_name;
+	  append_table (ptr, pt, table_name, parent_table);
+	  pt = pt->next;
+      }
+}
+
+static void
+set_xml_filename (struct xml_params *ptr, const char *path)
+{
+/* saving the XML (input) filename */
+    int len = strlen (path);
+    char *xpath = malloc (len + 1);
+    const char *filename;
+    strcpy (xpath, path);
+    filename = basename (xpath);
+    len = strlen (filename);
+    ptr->filename = malloc (len + 1);
+    strcpy (ptr->filename, filename);
+    free (xpath);
+}
+
+static void
+params_cleanup (struct xml_params *ptr)
+{
+/* memory cleanup - params */
+    struct xml_tag *pt;
+    struct xml_tag *ptn;
+    struct sql_table *ps;
+    struct sql_table *psn;
+    if (ptr == NULL)
+	return;
+
+    pt = ptr->first_tag;
+    while (pt != NULL)
+      {
+	  ptn = pt->next;
+	  destroy_tag (pt);
+	  pt = ptn;
+      }
+    while (1)
+      {
+	  if (ptr->stack == NULL)
+	      break;
+	  pop_stack (ptr);
+      }
+    ps = ptr->first_table;
+    while (ps != NULL)
+      {
+	  psn = ps->next;
+	  destroy_table (ps);
+	  ps = psn;
+      }
+    if (ptr->filename != NULL)
+	free (ptr->filename);
+    if (ptr->CharData != NULL)
+	free (ptr->CharData);
+    if (ptr->sort_array != NULL)
+	free (ptr->sort_array);
+    if (ptr->CollapsedGML != NULL)
+	gmlDynBufferDestroy (ptr->CollapsedGML);
+    if (ptr->CollapsedGMLMarker != NULL)
+	sqlite3_free (ptr->CollapsedGMLMarker);
+}
+
+static void
+split_namespace (const char *str, char **ns, char **name)
+{
+/* attempting to divide an XML identifier into a namespace and a name */
+    int i;
+    int len;
+    int pos = -1;
+    *ns = NULL;
+    *name = NULL;
+
+    len = strlen (str);
+    for (i = 0; i < len; i++)
+      {
+	  if (str[i] == ':')
+	    {
+		pos = i;
+		break;
+	    }
+      }
+    if (pos < 0)
+      {
+	  *name = malloc (len + 1);
+	  strcpy (*name, str);
+	  return;
+      }
+    *ns = malloc (pos + 1);
+    memset (*ns, '\0', pos + 1);
+    memcpy (*ns, str, pos);
+    len = strlen (str + pos + 1);
+    *name = malloc (len + 1);
+    strcpy (*name, str + pos + 1);
+}
+
+static int
+is_gml_geometry (const char *ns, const char *name)
+{
+/* testing a possible GML Geometry */
+    int is_gml = 0;
+    int is_gml_ns = 0;
+    if (strcmp (name, "Point") == 0)
+	is_gml = 1;
+    if (strcmp (name, "LineString") == 0)
+	is_gml = 1;
+    if (strcmp (name, "Curve") == 0)
+	is_gml = 1;
+    if (strcmp (name, "Polygon") == 0)
+	is_gml = 1;
+    if (strcmp (name, "MultiPoint") == 0)
+	is_gml = 1;
+    if (strcmp (name, "MultiLineString") == 0)
+	is_gml = 1;
+    if (strcmp (name, "MultiCurve") == 0)
+	is_gml = 1;
+    if (strcmp (name, "MultiPolygon") == 0)
+	is_gml = 1;
+    if (strcmp (name, "MultiSurface") == 0)
+	is_gml = 1;
+    if (strcmp (name, "MultiGeometry") == 0)
+	is_gml = 1;
+    if (ns == NULL)
+	is_gml_ns = 1;
+    else if (strcmp (ns, "gml") == 0)
+	is_gml_ns = 1;
+    if (!is_gml_ns)
+	is_gml = 0;
+    return is_gml;
+}
+
+static char *
+build_full_name (struct stack_entry *entry, const char *name)
+{
+/* building a fully qualified tag name */
+    int i;
+    char *str = NULL;
+    struct stack_entry *pe = entry;
+    while (pe != NULL)
+      {
+	  if (str != NULL)
+	    {
+		char *tmp = sqlite3_mprintf ("%s_%s", pe->tag_name, str);
+		sqlite3_free (str);
+		str = tmp;
+	    }
+	  else
+	      str = sqlite3_mprintf ("%s", pe->tag_name);
+	  pe = pe->prev;
+      }
+    if (str != NULL)
+      {
+	  char *tmp = sqlite3_mprintf ("%s_%s", str, name);
+	  sqlite3_free (str);
+	  str = tmp;
+      }
+    else
+	str = sqlite3_mprintf ("%s", name);
+    for (i = 0; i < (int) strlen (str); i++)
+      {
+	  char c = *(str + i);
+	  if (c >= 'A' && c <= 'Z')
+	      *(str + i) = c - 'A' + 'a';
+      }
+    return str;
+}
+
+static void
+start_tag_1 (void *data, const char *el, const char **attr)
+{
+/* XML element starting - Pass I */
+    const char **attrib = attr;
+    int count = 0;
+    const char *k;
+    char *ns = NULL;
+    char *name = NULL;
+    char *full_name = NULL;
+    char *parent_full_name = NULL;
+    struct xml_params *params = (struct xml_params *) data;
+    struct xml_tag *tag;
+    if (params->CollapsingGML)
+      {
+	  /* collapsing GML Geometries */
+	  *(params->CharData) = '\0';
+	  params->CharDataLen = 0;
+	  return;
+      }
+    split_namespace (el, &ns, &name);
+    if (params->collapsed_gml)
+      {
+	  /* attempting to collapse GML Geometries */
+	  if (is_gml_geometry (ns, name))
+	    {
+		if (ns != NULL)
+		    free (ns);
+		if (name != NULL)
+		    free (name);
+		params->CollapsingGML = 1;
+		if (params->CollapsedGMLMarker != NULL)
+		    sqlite3_free (params->CollapsedGMLMarker);
+		params->CollapsedGMLMarker = sqlite3_mprintf ("%s", el);
+		*(params->CharData) = '\0';
+		params->CharDataLen = 0;
+		return;
+	    }
+      }
+    params->treeLevel += 1;
+    full_name = build_full_name (params->stack, name);
+    tag = find_tag (params, ns, name, full_name);
+    if (tag == NULL)
+      {
+	  struct xml_tag *parent = NULL;
+	  if (params->stack != NULL)
+	    {
+		struct stack_entry *entry = params->stack;
+		parent_full_name =
+		    build_full_name (entry->prev, entry->tag_name);
+		parent =
+		    find_tag (params, entry->tag_ns, entry->tag_name,
+			      parent_full_name);
+		sqlite3_free (parent_full_name);
+	    }
+	  tag = append_tag (params, ns, name, full_name, parent);
+      }
+    else
+	sqlite3_free (full_name);
+    push_stack (params, ns, name);
+    while (*attrib != NULL)
+      {
+	  if ((count % 2) == 0)
+	      k = *attrib;
+	  else
+	    {
+		split_namespace (k, &ns, &name);
+		append_attribute (tag, ns, name);
+	    }
+	  attrib++;
+	  count++;
+      }
+    *(params->CharData) = '\0';
+    params->CharDataLen = 0;
+}
+
+static void
+end_tag_1 (void *data, const char *el)
+{
+/* XML element ending - Pass I */
+    struct xml_params *params = (struct xml_params *) data;
+    if (params->CollapsingGML)
+      {
+	  /* collapsing GML Geometries */
+	  if (strcmp (params->CollapsedGMLMarker, el) == 0)
+	    {
+		char *full_name = build_full_name (params->stack->prev,
+						   params->stack->tag_name);
+		struct xml_tag *tag = find_tag (params, params->stack->tag_ns,
+						params->stack->tag_name,
+						full_name);
+		sqlite3_free (full_name);
+		tag->has_geometry = 1;
+		params->CollapsingGML = 0;
+	    }
+	  *(params->CharData) = '\0';
+	  params->CharDataLen = 0;
+	  return;
+      }
+    params->treeLevel -= 1;
+    *(params->CharData) = '\0';
+    params->CharDataLen = 0;
+    pop_stack (params);
+}
+
+static int
+create_sql_table (sqlite3 * db_handle, struct sql_table *tbl, int xlink_href)
+{
+/* attempting to create a SQL Table (if not already existing) */
+    int ret;
+    char *err_msg = NULL;
+    char *sql;
+    struct xml_attr *attr;
+    int xlink_href_index = 0;
+    int gml_id_index = 0;
+    sql = sqlite3_mprintf ("CREATE TABLE IF NOT EXISTS \"%s\" (\n"
+			   "node_id INTEGER PRIMARY KEY AUTOINCREMENT,\n",
+			   tbl->table_name);
+    if (tbl->parent_table != NULL)
+      {
+	  /* defining the Foreign Key column */
+	  char *sql1 = sqlite3_mprintf ("%sparent_id INTEGER NOT NULL,\n", sql);
+	  sqlite3_free (sql);
+	  sql = sql1;
+      }
+    else
+      {
+	  /* defining the "mtdapp_filename" column */
+	  char *sql1 =
+	      sqlite3_mprintf ("%smtdapp_filename TEXT NOT NULL,\n", sql);
+	  sqlite3_free (sql);
+	  sql = sql1;
+      }
+    attr = tbl->tag->first_attr;
+    while (attr != NULL)
+      {
+	  /* defining any attribute  column */
+	  char *sql1;
+	  if (xlink_href)
+	    {
+		int is_xlink = 0;
+		int is_gml = 0;
+		if (attr->attr_ns != NULL)
+		  {
+		      if (strcmp (attr->attr_ns, "xlink") == 0)
+			  is_xlink = 1;
+		      if (strcmp (attr->attr_ns, "gml") == 0)
+			  is_gml = 1;
+		  }
+		if (is_xlink && strcmp (attr->attr_name, "href") == 0)
+		  {
+		      sql1 =
+			  sqlite3_mprintf ("%s\"%s\" TEXT,\n", sql,
+					   "xlink_href");
+		      sqlite3_free (sql);
+		      sql = sql1;
+		      xlink_href_index = 1;
+		      attr = attr->next;
+		      continue;
+		  }
+		if (is_gml && strcmp (attr->attr_name, "id") == 0)
+		  {
+		      sql1 =
+			  sqlite3_mprintf ("%s\"%s\" TEXT,\n", sql, "gml_id");
+		      sqlite3_free (sql);
+		      sql = sql1;
+		      gml_id_index = 1;
+		      attr = attr->next;
+		      continue;
+		  }
+	    }
+	  sql1 = sqlite3_mprintf ("%s\"%s\" TEXT,\n", sql, attr->attr_name);
+	  sqlite3_free (sql);
+	  sql = sql1;
+	  attr = attr->next;
+      }
+    if (tbl->parent_table != NULL)
+      {
+	  /* declaring the Foreign Key Constraint */
+	  char *sql1;
+	  if (tbl->tag->has_geometry)
+	    {
+		sql1 =
+		    sqlite3_mprintf
+		    ("%snode_value TEXT,\nfrom_gml_geometry BLOB\n,"
+		     "CONSTRAINT \"fk_%s\" FOREIGN KEY (parent_id) "
+		     "REFERENCES \"%s\" (node_id) ON DELETE CASCADE)", sql,
+		     tbl->table_name, tbl->parent_table);
+	    }
+	  else
+	    {
+		sql1 = sqlite3_mprintf ("%snode_value TEXT,\n"
+					"CONSTRAINT \"fk_%s\" FOREIGN KEY (parent_id) "
+					"REFERENCES \"%s\" (node_id) ON DELETE CASCADE)",
+					sql, tbl->table_name,
+					tbl->parent_table);
+	    }
+	  sqlite3_free (sql);
+	  sql = sql1;
+      }
+    else
+      {
+	  /* root table */
+	  char *sql1;
+	  if (tbl->tag->has_geometry)
+	      sql1 =
+		  sqlite3_mprintf
+		  ("%snode_value TEXT,\nfrom_gml_geometry BLOB)", sql);
+	  else
+	      sql1 = sqlite3_mprintf ("%snode_value TEXT)", sql);
+	  sqlite3_free (sql);
+	  sql = sql1;
+      }
+/* executing the SQL statement */
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE TABLE error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+
+    if (tbl->parent_table != NULL)
+      {
+	  /* creating an Index supporting the Foreign Key */
+	  sql = sqlite3_mprintf ("CREATE INDEX IF NOT EXISTS "
+				 "\"idx_%s\" ON \"%s\" (parent_id)",
+				 tbl->table_name, tbl->table_name);
+	  ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+	  sqlite3_free (sql);
+	  if (ret != SQLITE_OK)
+	    {
+		fprintf (stderr, "CREATE INDEX [FK] error: %s\n", err_msg);
+		sqlite3_free (err_msg);
+		return 0;
+	    }
+      }
+
+    if (xlink_href_index)
+      {
+	  /* creating an Index supporting the xlink_href column */
+	  sql = sqlite3_mprintf ("CREATE INDEX IF NOT EXISTS "
+				 "\"idx_%s_xlink_href\" ON \"%s\" (xlink_href)",
+				 tbl->table_name, tbl->table_name);
+	  ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+	  sqlite3_free (sql);
+	  if (ret != SQLITE_OK)
+	    {
+		fprintf (stderr, "CREATE INDEX [xlink_href] error: %s\n",
+			 err_msg);
+		sqlite3_free (err_msg);
+		return 0;
+	    }
+      }
+
+    if (gml_id_index)
+      {
+	  /* creating an Index supporting the gnk_id column */
+	  sql = sqlite3_mprintf ("CREATE INDEX IF NOT EXISTS "
+				 "\"idx_%s_gml_id\" ON \"%s\" (gml_id)",
+				 tbl->table_name, tbl->table_name);
+	  ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+	  sqlite3_free (sql);
+	  if (ret != SQLITE_OK)
+	    {
+		fprintf (stderr, "CREATE INDEX [gml_id] error: %s\n", err_msg);
+		sqlite3_free (err_msg);
+		return 0;
+	    }
+      }
+    return 1;
+}
+
+static int
+check_baseline_table (sqlite3 * db_handle, struct sql_table *tbl)
+{
+/* checking the expected baseline definition for some table */
+    int ret;
+    char *err_msg = NULL;
+    char **results;
+    int rows;
+    int columns;
+    int i;
+    int ok_pk = 0;
+    int ok_fk = 0;
+    int ok_value = 0;
+    int error = 0;
+
+/* checking the expected columns */
+    char *sql = sqlite3_mprintf ("PRAGMA table_info(\"%s\")", tbl->table_name);
+    ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "PRAGMA table_info error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+    if (rows < 1)
+	;
+    else
+      {
+	  for (i = 1; i <= rows; i++)
+	    {
+		const char *name = results[(i * columns) + 1];
+		if (strcmp (name, "node_id") == 0)
+		  {
+		      if (atoi (results[(i * columns) + 5]) == 1)
+			  ok_pk = 1;
+		      else
+			{
+			    fprintf (stderr,
+				     "TABLE \"%s\": column \"node_id\" isn't defined as a PRIMARY KEY\n",
+				     tbl->table_name);
+			    error = 1;
+			}
+		  }
+		else if (atoi (results[(i * columns) + 5]) == 1)
+		  {
+		      fprintf (stderr,
+			       "TABLE \"%s\": unexpected column \"%s\" defined as a PRIMARY KEY\n",
+			       tbl->table_name, name);
+		      error = 1;
+		  }
+		if (strcmp (name, "parent_id") == 0)
+		    ok_fk = 1;
+		if (strcmp (name, "node_value") == 0)
+		    ok_value = 1;
+	    }
+      }
+    sqlite3_free_table (results);
+    if (error)
+	return 0;
+    if (ok_pk == 0)
+      {
+	  fprintf (stderr,
+		   "TABLE \"%s\": unable to found the expected \"node_id\" PRIMARY KEY\n",
+		   tbl->table_name);
+	  return 0;
+      }
+    if (tbl->parent_table != NULL && ok_fk == 0)
+      {
+	  fprintf (stderr,
+		   "TABLE \"%s\": unable to found the expected \"parent_id\" column\n",
+		   tbl->table_name);
+	  return 0;
+      }
+    if (tbl->parent_table == NULL && ok_fk != 0)
+      {
+	  fprintf (stderr,
+		   "TABLE \"%s\": found an unexpected \"parent_id\" column\n",
+		   tbl->table_name);
+	  return 0;
+      }
+    if (ok_value == 0)
+      {
+	  fprintf (stderr,
+		   "TABLE \"%s\": unable to found the expected \"node_value\" column\n",
+		   tbl->table_name);
+	  return 0;
+      }
+
+    ok_fk = 0;
+    if (tbl->parent_table != NULL)
+      {
+	  /* checking the Foreing Key */
+	  char *sql = sqlite3_mprintf ("PRAGMA foreign_key_list(\"%s\")",
+				       tbl->table_name);
+	  ret =
+	      sqlite3_get_table (db_handle, sql, &results, &rows, &columns,
+				 NULL);
+	  sqlite3_free (sql);
+	  if (ret != SQLITE_OK)
+	    {
+		fprintf (stderr, "PRAGMA foreign_key_list error: %s\n",
+			 err_msg);
+		sqlite3_free (err_msg);
+		return 0;
+	    }
+	  if (rows < 1)
+	      ;
+	  else
+	    {
+		for (i = 1; i <= rows; i++)
+		  {
+		      const char *name = results[(i * columns) + 2];
+		      if (strcmp (name, tbl->parent_table) != 0)
+			{
+			    fprintf (stderr,
+				     "TABLE \"%s\": mismatching FOREIGN KEY [references \"%s\"]\n",
+				     tbl->table_name, name);
+			    error = 1;
+			}
+		      else
+			  ok_fk = 1;
+		      if (strcmp (results[(i * columns) + 3], "parent_id") != 0
+			  || strcmp (results[(i * columns) + 4],
+				     "node_id") != 0)
+			{
+			    fprintf (stderr,
+				     "TABLE \"%s\": mismatching FOREIGN KEY [not \"parent_id\" -> \"node_id\"]\n",
+				     tbl->table_name);
+			    error = 1;
+			}
+		  }
+	    }
+	  sqlite3_free_table (results);
+	  if (error)
+	      return 0;
+	  if (ok_fk == 0)
+	    {
+		fprintf (stderr,
+			 "TABLE \"%s\": unable to found the expected FOREIGN KEY\n",
+			 tbl->table_name);
+		return 0;
+	    }
+      }
+    return 1;
+}
+
+static int
+upgrade_sql_table (sqlite3 * db_handle, struct sql_table *tbl, int xlink_href)
+{
+/* attempting to upgrade some table */
+    int ret;
+    char *err_msg = NULL;
+    char **results;
+    int rows;
+    int columns;
+    int i;
+    struct xml_attr *attr;
+
+/* checking the attribute columns */
+    char *sql = sqlite3_mprintf ("PRAGMA table_info(\"%s\")", tbl->table_name);
+    ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "PRAGMA table_info error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+    if (rows < 1)
+	;
+    else
+      {
+	  for (i = 1; i <= rows; i++)
+	    {
+		const char *name = results[(i * columns) + 1];
+		attr = tbl->tag->first_attr;
+		while (attr != NULL)
+		  {
+		      if (xlink_href)
+			{
+			    /* special cases: xlink_href and gml_id */
+			    int is_xlink = 0;
+			    int is_gml = 0;
+			    if (attr->attr_ns != NULL)
+			      {
+				  if (strcmp (attr->attr_ns, "xlink") == 0)
+				      is_xlink = 1;
+				  if (strcmp (attr->attr_ns, "gml") == 0)
+				      is_gml = 1;
+			      }
+			    if (is_xlink
+				&& strcmp (attr->attr_name, "href") == 0)
+			      {
+				  if (strcmp (name, "xlink_href") == 0)
+				    {
+					attr->exists = 1;
+					attr = attr->next;
+					continue;
+				    }
+			      }
+			    if (is_gml && strcmp (attr->attr_name, "id") == 0)
+			      {
+				  if (strcmp (name, "gml_id") == 0)
+				    {
+					attr->exists = 1;
+					attr = attr->next;
+					continue;
+				    }
+			      }
+			}
+		      if (strcmp (attr->attr_name, name) == 0)
+			  attr->exists = 1;
+		      attr = attr->next;
+		  }
+	    }
+      }
+    sqlite3_free_table (results);
+
+    attr = tbl->tag->first_attr;
+    while (attr != NULL)
+      {
+	  if (attr->exists != 1)
+	    {
+		/* attempting to add an attribute column */
+		sql =
+		    sqlite3_mprintf
+		    ("ALTER TABLE \"%s\" ADD COLUMN \"%s\" TEXT",
+		     tbl->table_name, attr->attr_name);
+		ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+		sqlite3_free (sql);
+		if (ret != SQLITE_OK)
+		  {
+		      fprintf (stderr, "ALTER TABLE error: %s\n", err_msg);
+		      sqlite3_free (err_msg);
+		      return 0;
+		  }
+	    }
+	  attr = attr->next;
+      }
+    return 1;
+}
+
+static int
+prepare_sql_statements (sqlite3 * db_handle, struct sql_table *tbl,
+			int xlink_href)
+{
+/* preparing the INSERT and UPDATE SQL statements */
+    struct xml_attr *attr;
+    char *sql;
+    char *sql1;
+    int ret;
+    sqlite3_stmt *stmt;
+
+/* preparing the INSERT statement */
+    if (tbl->parent_table == NULL)
+	sql =
+	    sqlite3_mprintf ("INSERT INTO \"%s\" (node_id, mtdapp_filename",
+			     tbl->table_name);
+    else
+	sql =
+	    sqlite3_mprintf ("INSERT INTO \"%s\" (node_id, parent_id",
+			     tbl->table_name);
+    attr = tbl->tag->first_attr;
+    while (attr != NULL)
+      {
+	  if (xlink_href)
+	    {
+		/* special cases: xlink_href and gml_id */
+		int is_xlink = 0;
+		int is_gml = 0;
+		if (attr->attr_ns != NULL)
+		  {
+		      if (strcmp (attr->attr_ns, "xlink") == 0)
+			  is_xlink = 1;
+		      if (strcmp (attr->attr_ns, "gml") == 0)
+			  is_gml = 1;
+		  }
+		if (is_xlink && strcmp (attr->attr_name, "href") == 0)
+		  {
+		      sql1 = sqlite3_mprintf ("%s, xlink_href", sql);
+		      sqlite3_free (sql);
+		      sql = sql1;
+		      attr = attr->next;
+		      continue;
+		  }
+		if (is_gml && strcmp (attr->attr_name, "id") == 0)
+		  {
+		      sql1 = sqlite3_mprintf ("%s, gml_id", sql);
+		      sqlite3_free (sql);
+		      sql = sql1;
+		      attr = attr->next;
+		      continue;
+		  }
+	    }
+	  sql1 = sqlite3_mprintf ("%s, \"%s\"", sql, attr->attr_name);
+	  sqlite3_free (sql);
+	  sql = sql1;
+	  attr = attr->next;
+      }
+    sql1 = sqlite3_mprintf ("%s) VALUES (NULL, ?", sql);
+    sqlite3_free (sql);
+    sql = sql1;
+    attr = tbl->tag->first_attr;
+    while (attr != NULL)
+      {
+	  sql1 = sqlite3_mprintf ("%s, ?", sql);
+	  sqlite3_free (sql);
+	  sql = sql1;
+	  attr = attr->next;
+      }
+    sql1 = sqlite3_mprintf ("%s)", sql);
+    sqlite3_free (sql);
+    sql = sql1;
+    ret = sqlite3_prepare_v2 (db_handle, sql, strlen (sql), &stmt, NULL);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "INSERT INTO error: %s\n",
+		   sqlite3_errmsg (db_handle));
+	  return 0;
+      }
+    tbl->ins_stmt = stmt;
+
+/* preparing the UPDATE statement */
+    if (tbl->tag->has_geometry)
+	sql = sqlite3_mprintf ("UPDATE \"%s\" SET node_value = ?, "
+			       "from_gml_geometry = ? WHERE node_id = ?",
+			       tbl->table_name);
+    else
+	sql =
+	    sqlite3_mprintf
+	    ("UPDATE \"%s\" SET node_value = ? WHERE node_id = ?",
+	     tbl->table_name);
+    ret = sqlite3_prepare_v2 (db_handle, sql, strlen (sql), &stmt, NULL);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "UPDATE error: %s\n", sqlite3_errmsg (db_handle));
+	  return 0;
+      }
+    tbl->upd_stmt = stmt;
+    return 1;
+}
+
+static int
+prepare_sql_tables (struct xml_params *ptr)
+{
+/* creating/updating the SQL tables */
+    int ret;
+    int error = 0;
+    const char *sql;
+    char *err_msg;
+    sqlite3_stmt *stmt;
+    struct sql_table *tbl = ptr->first_table;
+    while (tbl != NULL)
+      {
+	  ret = create_sql_table (ptr->db_handle, tbl, ptr->xlink_href);
+	  if (!ret)
+	      return 0;
+	  ret = check_baseline_table (ptr->db_handle, tbl);
+	  if (!ret)
+	      return 0;
+	  ret = upgrade_sql_table (ptr->db_handle, tbl, ptr->xlink_href);
+	  if (!ret)
+	      return 0;
+	  ret = prepare_sql_statements (ptr->db_handle, tbl, ptr->xlink_href);
+	  if (!ret)
+	      return 0;
+	  tbl = tbl->next;
+      }
+
+/* creating the "xml_metacatalog_tables" table */
+    sql = "CREATE TABLE IF NOT EXISTS xml_metacatalog_tables (\n"
+	"table_name TEXT NOT NULL PRIMARY KEY,\n"
+	"tree_level INTEGER NOT NULL,\n"
+	"xml_tag_namespace TEXT,\n"
+	"xml_tag_name TEXT NOT NULL,\n"
+	"parent_table_name TEXT,\n"
+	"gml_geometry_column TEXT,\n"
+	"status TEXT NOT NULL,\n"
+	"CONSTRAINT fk_xml_meta_tables FOREIGN KEY (parent_table_name) "
+	"REFERENCES xml_metacatalog_tables (table_name))";
+    ret = sqlite3_exec (ptr->db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE TABLE xml_meta_catalog_tables error: %s\n",
+		   err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+
+/* prepared statement for INSERT INTO xml_metacatalog_tables */
+    sql =
+	"INSERT OR IGNORE INTO xml_metacatalog_tables (table_name, tree_level, "
+	"xml_tag_namespace, xml_tag_name, parent_table_name, "
+	"gml_geometry_column, status) VALUES (?, ?, ?, ?, ?, ?, ?)";
+    ret = sqlite3_prepare_v2 (ptr->db_handle, sql, strlen (sql), &stmt, NULL);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "INSERT INTO xml_metacatalog_tables error: %s\n",
+		   sqlite3_errmsg (ptr->db_handle));
+	  return 0;
+      }
+
+/* updating "xml_metacatalog_tables" */
+    tbl = ptr->first_table;
+    while (tbl != NULL)
+      {
+	  const char *str;
+	  sqlite3_reset (stmt);
+	  sqlite3_clear_bindings (stmt);
+	  sqlite3_bind_text (stmt, 1, tbl->table_name, strlen (tbl->table_name),
+			     SQLITE_STATIC);
+	  sqlite3_bind_int (stmt, 2, tbl->tag->tree_level);
+	  if (tbl->tag->tag_ns == NULL)
+	      sqlite3_bind_null (stmt, 3);
+	  else
+	      sqlite3_bind_text (stmt, 3, tbl->tag->tag_ns,
+				 strlen (tbl->tag->tag_ns), SQLITE_STATIC);
+	  sqlite3_bind_text (stmt, 4, tbl->tag->tag_name,
+			     strlen (tbl->tag->tag_name), SQLITE_STATIC);
+	  if (tbl->parent_table == NULL)
+	      sqlite3_bind_null (stmt, 5);
+	  else
+	      sqlite3_bind_text (stmt, 5, tbl->parent_table,
+				 strlen (tbl->parent_table), SQLITE_STATIC);
+	  if (tbl->tag->has_geometry)
+	    {
+		str = "from_gml_geometry";
+		sqlite3_bind_text (stmt, 6, str, strlen (str), SQLITE_STATIC);
+	    }
+	  else
+	      sqlite3_bind_null (stmt, 6);
+	  str = "raw (not post-processed)";
+	  sqlite3_bind_text (stmt, 7, str, strlen (str), SQLITE_STATIC);
+	  ret = sqlite3_step (stmt);
+	  if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+	      ;
+	  else
+	    {
+		fprintf (stderr, "INSERT xml_metacatalog_tables error: %s\n",
+			 sqlite3_errmsg (ptr->db_handle));
+		error = 1;
+		goto stop;
+	    }
+	  tbl = tbl->next;
+      }
+  stop:
+    sqlite3_finalize (stmt);
+
+/* creating the "xml_metacatalog_columns" table */
+    sql = "CREATE TABLE IF NOT EXISTS xml_metacatalog_columns (\n"
+	"table_name TEXT NOT NULL,\n"
+	"column_name TEXT NOT NULL,\n"
+	"origin TEXT NOT NULL,\n"
+	"destination TEXT,\n"
+	"xml_reference TEXT NOT NULL,\n"
+	"CONSTRAINT pk_xml_meta_columns PRIMARY KEY (table_name, column_name),\n"
+	"CONSTRAINT fk_xml_meta_columns FOREIGN KEY (table_name) "
+	"REFERENCES xml_metacatalog_tables (table_name))";
+    ret = sqlite3_exec (ptr->db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE TABLE xml_meta_catalog_columns error: %s\n",
+		   err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+
+/* prepared statement for INSERT INTO xml_metacatalog_columns */
+    sql =
+	"INSERT OR IGNORE INTO xml_metacatalog_columns (table_name, column_name, "
+	"origin, destination, xml_reference) VALUES (?, ?, ?, NULL, ?)";
+    ret = sqlite3_prepare_v2 (ptr->db_handle, sql, strlen (sql), &stmt, NULL);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "INSERT INTO xml_metacatalog_columns error: %s\n",
+		   sqlite3_errmsg (ptr->db_handle));
+	  return 0;
+      }
+
+/* updating "xml_metacatalog_columns" */
+    tbl = ptr->first_table;
+    while (tbl != NULL)
+      {
+	  char *xml;
+	  const char *str;
+	  struct xml_attr *attr;
+	  /* node_id column */
+	  sqlite3_reset (stmt);
+	  sqlite3_clear_bindings (stmt);
+	  sqlite3_bind_text (stmt, 1, tbl->table_name, strlen (tbl->table_name),
+			     SQLITE_STATIC);
+	  str = "node_id";
+	  sqlite3_bind_text (stmt, 2, str, strlen (str), SQLITE_STATIC);
+	  str = "DBMS internal identifier - Primary Key";
+	  sqlite3_bind_text (stmt, 3, str, strlen (str), SQLITE_STATIC);
+	  str = "n.a.";
+	  sqlite3_bind_text (stmt, 4, str, strlen (str), SQLITE_STATIC);
+	  ret = sqlite3_step (stmt);
+	  if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+	      ;
+	  else
+	    {
+		fprintf (stderr, "INSERT xml_metacatalog_columns error: %s\n",
+			 sqlite3_errmsg (ptr->db_handle));
+		error = 1;
+		goto stop2;
+	    }
+	  if (tbl->parent_table != NULL)
+	    {
+		/* parent_id column */
+		sqlite3_reset (stmt);
+		sqlite3_clear_bindings (stmt);
+		sqlite3_bind_text (stmt, 1, tbl->table_name,
+				   strlen (tbl->table_name), SQLITE_STATIC);
+		str = "parent_id";
+		sqlite3_bind_text (stmt, 2, str, strlen (str), SQLITE_STATIC);
+		str = "DBMS internal identifier - Foreign Key";
+		sqlite3_bind_text (stmt, 3, str, strlen (str), SQLITE_STATIC);
+		str = "n.a.";
+		sqlite3_bind_text (stmt, 4, str, strlen (str), SQLITE_STATIC);
+		ret = sqlite3_step (stmt);
+		if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+		    ;
+		else
+		  {
+		      fprintf (stderr,
+			       "INSERT xml_metacatalog_columns error: %s\n",
+			       sqlite3_errmsg (ptr->db_handle));
+		      error = 1;
+		      goto stop2;
+		  }
+	    }
+	  /* node_value column */
+	  sqlite3_reset (stmt);
+	  sqlite3_clear_bindings (stmt);
+	  sqlite3_bind_text (stmt, 1, tbl->table_name, strlen (tbl->table_name),
+			     SQLITE_STATIC);
+	  str = "node_value";
+	  sqlite3_bind_text (stmt, 2, str, strlen (str), SQLITE_STATIC);
+	  str = "imported from XML Node value";
+	  sqlite3_bind_text (stmt, 3, str, strlen (str), SQLITE_STATIC);
+	  if (tbl->tag->tag_ns == NULL)
+	      xml =
+		  sqlite3_mprintf ("<%s>value</%s>",
+				   tbl->tag->tag_name, tbl->tag->tag_name);
+	  else
+	      xml =
+		  sqlite3_mprintf ("<%s:%s>value</%s:%s>",
+				   tbl->tag->tag_ns,
+				   tbl->tag->tag_name,
+				   tbl->tag->tag_ns, tbl->tag->tag_name);
+	  sqlite3_bind_text (stmt, 4, xml, strlen (xml), sqlite3_free);
+	  ret = sqlite3_step (stmt);
+	  if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+	      ;
+	  else
+	    {
+		fprintf (stderr, "INSERT xml_metacatalog_columns error: %s\n",
+			 sqlite3_errmsg (ptr->db_handle));
+		error = 1;
+		goto stop2;
+	    }
+	  if (tbl->tag->has_geometry == 0)
+	    {
+		/* node_value_column */
+		sqlite3_reset (stmt);
+		sqlite3_clear_bindings (stmt);
+		sqlite3_bind_text (stmt, 1, tbl->table_name,
+				   strlen (tbl->table_name), SQLITE_STATIC);
+		str = "node_value";
+		sqlite3_bind_text (stmt, 2, str, strlen (str), SQLITE_STATIC);
+		str = "imported from XML node value";
+		sqlite3_bind_text (stmt, 3, str, strlen (str), SQLITE_STATIC);
+		if (tbl->tag->tag_ns == NULL)
+		    xml =
+			sqlite3_mprintf ("<%s>value</%s>", tbl->tag->tag_name,
+					 tbl->tag->tag_name);
+		else
+		    xml =
+			sqlite3_mprintf ("<%s:%s>value</%s:%s>",
+					 tbl->tag->tag_ns, tbl->tag->tag_name,
+					 tbl->tag->tag_ns, tbl->tag->tag_name);
+		sqlite3_bind_text (stmt, 4, xml, strlen (xml), sqlite3_free);
+		ret = sqlite3_step (stmt);
+		if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+		    ;
+		else
+		  {
+		      fprintf (stderr,
+			       "INSERT xml_metacatalog_columns error: %s\n",
+			       sqlite3_errmsg (ptr->db_handle));
+		      error = 1;
+		      goto stop2;
+		  }
+	    }
+	  else
+	    {
+		/* collapsed GML Geometry */
+		sqlite3_reset (stmt);
+		sqlite3_clear_bindings (stmt);
+		sqlite3_bind_text (stmt, 1, tbl->table_name,
+				   strlen (tbl->table_name), SQLITE_STATIC);
+		str = "node_value";
+		sqlite3_bind_text (stmt, 2, str, strlen (str), SQLITE_STATIC);
+		str = "imported from collapsed GML Geometry tags";
+		sqlite3_bind_text (stmt, 3, str, strlen (str), SQLITE_STATIC);
+		if (tbl->tag->tag_ns == NULL)
+		    xml =
+			sqlite3_mprintf ("<%s>gml_expr</%s>",
+					 tbl->tag->tag_name,
+					 tbl->tag->tag_name);
+		else
+		    xml =
+			sqlite3_mprintf ("<%s:%s>gml_expr</%s:%s>",
+					 tbl->tag->tag_ns, tbl->tag->tag_name,
+					 tbl->tag->tag_ns, tbl->tag->tag_name);
+		sqlite3_bind_text (stmt, 4, xml, strlen (xml), sqlite3_free);
+		ret = sqlite3_step (stmt);
+		if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+		    ;
+		else
+		  {
+		      fprintf (stderr,
+			       "INSERT xml_metacatalog_columns error: %s\n",
+			       sqlite3_errmsg (ptr->db_handle));
+		      error = 1;
+		      goto stop2;
+		  }
+		sqlite3_reset (stmt);
+		sqlite3_clear_bindings (stmt);
+		sqlite3_bind_text (stmt, 1, tbl->table_name,
+				   strlen (tbl->table_name), SQLITE_STATIC);
+		str = "from_gml_geometry";
+		sqlite3_bind_text (stmt, 2, str, strlen (str), SQLITE_STATIC);
+		str = "GeomFromGML(node_value)";
+		sqlite3_bind_text (stmt, 3, str, strlen (str), SQLITE_STATIC);
+		if (tbl->tag->tag_ns == NULL)
+		    xml =
+			sqlite3_mprintf ("<%s>gml_expr</%s>",
+					 tbl->tag->tag_name,
+					 tbl->tag->tag_name);
+		else
+		    xml =
+			sqlite3_mprintf ("<%s:%s>gml_expr</%s:%s>",
+					 tbl->tag->tag_ns, tbl->tag->tag_name,
+					 tbl->tag->tag_ns, tbl->tag->tag_name);
+		sqlite3_bind_text (stmt, 4, xml, strlen (xml), sqlite3_free);
+		ret = sqlite3_step (stmt);
+		if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+		    ;
+		else
+		  {
+		      fprintf (stderr,
+			       "INSERT xml_metacatalog_columns error: %s\n",
+			       sqlite3_errmsg (ptr->db_handle));
+		      error = 1;
+		      goto stop2;
+		  }
+	    }
+	  attr = tbl->tag->first_attr;
+	  while (attr != NULL)
+	    {
+		/* XML attributes */
+		sqlite3_reset (stmt);
+		sqlite3_clear_bindings (stmt);
+		sqlite3_bind_text (stmt, 1, tbl->table_name,
+				   strlen (tbl->table_name), SQLITE_STATIC);
+		if (ptr->xlink_href)
+		  {
+		      int is_xlink = 0;
+		      int is_gml = 0;
+		      if (attr->attr_ns != NULL)
+			{
+			    if (strcmp (attr->attr_ns, "xlink") == 0)
+				is_xlink = 1;
+			    if (strcmp (attr->attr_ns, "gml") == 0)
+				is_gml = 1;
+			}
+		      if (is_xlink && strcmp (attr->attr_name, "href") == 0)
+			{
+			    const char *xlhr = "xlink_href";
+			    sqlite3_bind_text (stmt, 2, xlhr, strlen (xlhr),
+					       SQLITE_STATIC);
+			}
+		      else if (is_gml && strcmp (attr->attr_name, "id") == 0)
+			{
+			    const char *gmid = "gml_id";
+			    sqlite3_bind_text (stmt, 2, gmid, strlen (gmid),
+					       SQLITE_STATIC);
+			}
+		      else
+			  sqlite3_bind_text (stmt, 2, attr->attr_name,
+					     strlen (attr->attr_name),
+					     SQLITE_STATIC);
+		  }
+		else
+		    sqlite3_bind_text (stmt, 2, attr->attr_name,
+				       strlen (attr->attr_name), SQLITE_STATIC);
+		str = "imported from XML attribute";
+		sqlite3_bind_text (stmt, 3, str, strlen (str), SQLITE_STATIC);
+		if (tbl->tag->tag_ns == NULL)
+		  {
+		      if (attr->attr_ns == NULL)
+			  xml =
+			      sqlite3_mprintf ("<%s %s=\"value\" />",
+					       tbl->tag->tag_name,
+					       attr->attr_name);
+		      else
+			  xml =
+			      sqlite3_mprintf ("<%s %s:%s=\"value\" />",
+					       tbl->tag->tag_name,
+					       attr->attr_ns, attr->attr_name);
+		  }
+		else
+		  {
+		      if (attr->attr_ns == NULL)
+			  xml =
+			      sqlite3_mprintf ("<%s:%s %s=\"value\" />",
+					       tbl->tag->tag_ns,
+					       tbl->tag->tag_name,
+					       attr->attr_name);
+		      else
+			  xml =
+			      sqlite3_mprintf ("<%s:%s %s:%s=\"value\" />",
+					       tbl->tag->tag_ns,
+					       tbl->tag->tag_name,
+					       attr->attr_ns, attr->attr_name);
+		  }
+		sqlite3_bind_text (stmt, 4, xml, strlen (xml), sqlite3_free);
+		ret = sqlite3_step (stmt);
+		if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+		    ;
+		else
+		  {
+		      fprintf (stderr,
+			       "INSERT xml_metacatalog_columns error: %s\n",
+			       sqlite3_errmsg (ptr->db_handle));
+		      error = 1;
+		      goto stop2;
+		  }
+		attr = attr->next;
+	    }
+	  tbl = tbl->next;
+      }
+  stop2:
+    sqlite3_finalize (stmt);
+
+    if (error)
+	return 0;
+    return 1;
+}
+
+static int
+do_insert (sqlite3 * db_handle, struct xml_tag *tag, const char *filename,
+	   int xlink_href)
+{
+/* attempting to INSERT an XML Node into the appropriate table */
+    struct xml_attr *attr;
+    int ret;
+    int pos = 1;
+    sqlite3_stmt *stmt = tag->table->ins_stmt;
+    sqlite3_reset (stmt);
+    sqlite3_clear_bindings (stmt);
+    if (tag->table->parent_table != NULL)
+      {
+	  /* retrieving the Foreign Key value */
+	  sqlite3_int64 fk_value = tag->parent->table->current;
+	  sqlite3_bind_int64 (stmt, pos, fk_value);
+	  pos++;
+      }
+    else
+      {
+	  /* setting the "mtdapp_filename" value */
+	  sqlite3_bind_text (stmt, pos, filename, strlen (filename),
+			     SQLITE_STATIC);
+	  pos++;
+      }
+    attr = tag->first_attr;
+    while (attr != NULL)
+      {
+	  if (xlink_href && attr->attr_value != NULL)
+	    {
+		/* special case: xlink_href */
+		int is_xlink = 0;
+		if (attr->attr_ns != NULL)
+		  {
+		      if (strcmp (attr->attr_ns, "xlink") == 0)
+			  is_xlink = 1;
+		  }
+		if (is_xlink && strcmp (attr->attr_name, "href") == 0)
+		  {
+		      if (*(attr->attr_value) == '#')
+			{
+			    /* skipping the initial # "anchor" marker */
+			    sqlite3_bind_text (stmt, pos, attr->attr_value + 1,
+					       strlen (attr->attr_value) - 1,
+					       SQLITE_STATIC);
+			    pos++;
+			    attr = attr->next;
+			}
+		      continue;
+		  }
+	    }
+	  if (attr->attr_value == NULL)
+	      sqlite3_bind_null (stmt, pos);
+	  else
+	      sqlite3_bind_text (stmt, pos, attr->attr_value,
+				 strlen (attr->attr_value), SQLITE_STATIC);
+	  pos++;
+	  attr = attr->next;
+      }
+/* INSERTing */
+    ret = sqlite3_step (stmt);
+    if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+	tag->table->current = sqlite3_last_insert_rowid (db_handle);
+    else
+      {
+	  fprintf (stderr, "INSERT error: %s\n", sqlite3_errmsg (db_handle));
+	  return 0;
+      }
+    return 1;
+}
+
+static int
+do_update (sqlite3 * db_handle, struct xml_tag *tag, const char *value, int len)
+{
+/* attempting to UPDATE an XML Node by setting the node's value */
+    int ret;
+    sqlite3_stmt *stmt = tag->table->upd_stmt;
+    sqlite3_reset (stmt);
+    sqlite3_clear_bindings (stmt);
+    sqlite3_bind_text (stmt, 1, value, len, SQLITE_STATIC);
+    sqlite3_bind_int64 (stmt, 2, tag->table->current);
+/* UPDATing */
+    ret = sqlite3_step (stmt);
+    if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+	;
+    else
+      {
+	  fprintf (stderr, "UPDATE error: %s\n", sqlite3_errmsg (db_handle));
+	  return 0;
+      }
+    return 1;
+}
+
+static int
+do_update_with_geom (sqlite3 * db_handle, struct xml_tag *tag,
+		     const char *value, int len)
+{
+/* attempting to UPDATE an XML Node by setting the node's value */
+    int ret;
+    gaiaGeomCollPtr geo;
+    unsigned char *gml_expr;
+    sqlite3_stmt *stmt = tag->table->upd_stmt;
+    sqlite3_reset (stmt);
+    sqlite3_clear_bindings (stmt);
+    sqlite3_bind_text (stmt, 1, value, len, SQLITE_STATIC);
+    gml_expr = malloc (len + 1);
+    memcpy (gml_expr, value, len);
+    *(gml_expr + len) = '\0';
+    geo = gaiaParseGml (gml_expr, db_handle);
+    free (gml_expr);
+    if (geo == NULL)
+	sqlite3_bind_null (stmt, 2);
+    else
+      {
+	  int blob_len;
+	  unsigned char *blob;
+	  gaiaToSpatiaLiteBlobWkb (geo, &blob, &blob_len);
+	  gaiaFreeGeomColl (geo);
+	  sqlite3_bind_blob (stmt, 2, blob, blob_len, free);
+      }
+    sqlite3_bind_int64 (stmt, 3, tag->table->current);
+/* UPDATing */
+    ret = sqlite3_step (stmt);
+    if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+	;
+    else
+      {
+	  fprintf (stderr, "UPDATE error: %s\n", sqlite3_errmsg (db_handle));
+	  return 0;
+      }
+    return 1;
+}
+
+static void
+start_tag_2 (void *data, const char *el, const char **attr)
+{
+/* XML element starting - Pass II */
+    const char **attrib = attr;
+    int count = 0;
+    const char *k;
+    const char *v;
+    char *ns = NULL;
+    char *name = NULL;
+    char *full_name = NULL;
+    struct xml_params *params = (struct xml_params *) data;
+    struct xml_tag *tag;
+    if (params->CollapsingGML)
+      {
+	  /* collapsing GML Geometries */
+	  gmlDynBufferAppend (params->CollapsedGML, "<", 1);
+	  gmlDynBufferAppend (params->CollapsedGML, el, strlen (el));
+	  while (*attrib != NULL)
+	    {
+		if ((count % 2) == 0)
+		    k = *attrib;
+		else
+		  {
+		      v = *attrib;
+		      gmlDynBufferAppend (params->CollapsedGML, " ", 1);
+		      gmlDynBufferAppend (params->CollapsedGML, k, strlen (k));
+		      gmlDynBufferAppend (params->CollapsedGML, "=\"", 2);
+		      gmlDynBufferAppend (params->CollapsedGML, v, strlen (v));
+		      gmlDynBufferAppend (params->CollapsedGML, "\"", 1);
+		  }
+		attrib++;
+		count++;
+	    }
+	  gmlDynBufferAppend (params->CollapsedGML, ">", 1);
+	  *(params->CharData) = '\0';
+	  params->CharDataLen = 0;
+	  return;
+      }
+    split_namespace (el, &ns, &name);
+    if (params->collapsed_gml)
+      {
+	  /* attempting to collapse GML Geometries */
+	  if (is_gml_geometry (ns, name))
+	    {
+		if (ns != NULL)
+		    free (ns);
+		if (name != NULL)
+		    free (name);
+		if (params->CollapsedGML != NULL)
+		    gmlDynBufferDestroy (params->CollapsedGML);
+		params->CollapsedGML = gmlDynBufferAlloc ();
+		gmlDynBufferAppend (params->CollapsedGML, "<", 1);
+		gmlDynBufferAppend (params->CollapsedGML, el, strlen (el));
+		while (*attrib != NULL)
+		  {
+		      if ((count % 2) == 0)
+			  k = *attrib;
+		      else
+			{
+			    v = *attrib;
+			    gmlDynBufferAppend (params->CollapsedGML, " ", 1);
+			    gmlDynBufferAppend (params->CollapsedGML, k,
+						strlen (k));
+			    gmlDynBufferAppend (params->CollapsedGML, "=\"", 2);
+			    gmlDynBufferAppend (params->CollapsedGML, v,
+						strlen (v));
+			    gmlDynBufferAppend (params->CollapsedGML, "\"", 1);
+			}
+		      attrib++;
+		      count++;
+		  }
+		gmlDynBufferAppend (params->CollapsedGML, ">", 1);
+		params->CollapsingGML = 1;
+		if (params->CollapsedGMLMarker != NULL)
+		    sqlite3_free (params->CollapsedGMLMarker);
+		params->CollapsedGMLMarker = sqlite3_mprintf ("%s", el);
+		*(params->CharData) = '\0';
+		params->CharDataLen = 0;
+		return;
+	    }
+      }
+    full_name = build_full_name (params->stack, name);
+    tag = find_tag (params, ns, name, full_name);
+    sqlite3_free (full_name);
+    reset_tag_attributes (tag);
+    push_stack (params, ns, name);
+    while (*attrib != NULL)
+      {
+	  if ((count % 2) == 0)
+	      k = *attrib;
+	  else
+	    {
+		v = *attrib;
+		split_namespace (k, &ns, &name);
+		set_attribute_value (tag, ns, name, v);
+		if (ns != NULL)
+		    free (ns);
+		if (name != NULL)
+		    free (name);
+	    }
+	  attrib++;
+	  count++;
+      }
+    *(params->CharData) = '\0';
+    params->CharDataLen = 0;
+    if (!do_insert
+	(params->db_handle, tag, params->filename, params->xlink_href))
+	params->db_error = 1;
+}
+
+static void
+end_tag_2 (void *data, const char *el)
+{
+/* XML element ending - Pass II */
+    struct xml_params *params = (struct xml_params *) data;
+    if (params->CollapsingGML)
+      {
+	  /* collapsing GML Geometries */
+	  if (valid_char_data (params))
+	      gmlDynBufferAppend (params->CollapsedGML, params->CharData,
+				  params->CharDataLen);
+	  gmlDynBufferAppend (params->CollapsedGML, "</", 2);
+	  gmlDynBufferAppend (params->CollapsedGML, el, strlen (el));
+	  gmlDynBufferAppend (params->CollapsedGML, ">", 1);
+	  if (strcmp (params->CollapsedGMLMarker, el) == 0)
+	    {
+		sqlite3_free (params->CollapsedGMLMarker);
+		params->CollapsedGMLMarker = NULL;
+		params->CollapsingGML = 0;
+	    }
+	  *(params->CharData) = '\0';
+	  params->CharDataLen = 0;
+	  return;
+      }
+    if (params->CollapsedGML != NULL)
+      {
+	  /* updating the Node value - collapsed GML */
+	  char *full_name =
+	      build_full_name (params->stack->prev, params->stack->tag_name);
+	  struct xml_tag *tag =
+	      find_tag (params, params->stack->tag_ns, params->stack->tag_name,
+			full_name);
+	  sqlite3_free (full_name);
+	  if (!do_update_with_geom
+	      (params->db_handle, tag, params->CollapsedGML->Buffer,
+	       params->CollapsedGML->WriteOffset))
+	      params->db_error = 1;
+	  gmlDynBufferDestroy (params->CollapsedGML);
+	  params->CollapsedGML = NULL;
+	  goto done;
+      }
+    if (valid_char_data (params))
+      {
+	  /* updating the Node value */
+	  char *full_name =
+	      build_full_name (params->stack->prev, params->stack->tag_name);
+	  struct xml_tag *tag =
+	      find_tag (params, params->stack->tag_ns, params->stack->tag_name,
+			full_name);
+	  sqlite3_free (full_name);
+	  if (!do_update
+	      (params->db_handle, tag, params->CharData, params->CharDataLen))
+	      params->db_error = 1;
+      }
+  done:
+    *(params->CharData) = '\0';
+    params->CharDataLen = 0;
+    pop_stack (params);
+}
+
+static void
+spatialite_autocreate (sqlite3 * db)
+{
+/* attempting to perform self-initialization for a newly created DB */
+    int ret;
+    char sql[1024];
+    char *err_msg = NULL;
+    int count;
+    int i;
+    char **results;
+    int rows;
+    int columns;
+
+/* checking if this DB is really empty */
+    strcpy (sql, "SELECT Count(*) from sqlite_master");
+    ret = sqlite3_get_table (db, sql, &results, &rows, &columns, NULL);
+    if (ret != SQLITE_OK)
+	return;
+    if (rows < 1)
+	;
+    else
+      {
+	  for (i = 1; i <= rows; i++)
+	      count = atoi (results[(i * columns) + 0]);
+      }
+    sqlite3_free_table (results);
+
+    if (count > 0)
+	return;
+
+/* all right, it's empty: proceding to initialize */
+    strcpy (sql, "SELECT InitSpatialMetadata(1)");
+    ret = sqlite3_exec (db, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "InitSpatialMetadata() error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  return;
+      }
+}
+
+static void
+open_db (const char *path, sqlite3 ** handle, int cache_size, void *cache)
+{
+/* opening the DB */
+    sqlite3 *db_handle;
+    int ret;
+    char sql[1024];
+
+    *handle = NULL;
+    printf ("SQLite version: %s\n", sqlite3_libversion ());
+    printf ("SpatiaLite version: %s\n", spatialite_version ());
+
+    ret =
+	sqlite3_open_v2 (path, &db_handle,
+			 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "cannot open '%s': %s\n", path,
+		   sqlite3_errmsg (db_handle));
+	  sqlite3_close (db_handle);
+	  db_handle = NULL;
+	  return;
+      }
+    spatialite_init_ex (db_handle, cache, 0);
+    spatialite_autocreate (db_handle);
+
+    if (cache_size > 0)
+      {
+	  /* setting the CACHE-SIZE */
+	  sprintf (sql, "PRAGMA cache_size=%d", cache_size);
+	  sqlite3_exec (db_handle, sql, NULL, NULL, NULL);
+      }
+
+/* enabling PK/FK constraints */
+    sqlite3_exec (db_handle, "PRAGMA foreign_keys = 1", NULL, NULL, NULL);
+    *handle = db_handle;
+    return;
+}
+
+#ifndef timersub
+/* This is a copy from GNU C Library (GNU LGPL 2.1), sys/time.h. */
+#define timersub(a, b, result)                                               \
+  do {                                                                        \
+    (result)->tv_sec = (a)->tv_sec - (b)->tv_sec;                             \
+    (result)->tv_usec = (a)->tv_usec - (b)->tv_usec;                          \
+    if ((result)->tv_usec < 0) {                                              \
+      --(result)->tv_sec;                                                     \
+      (result)->tv_usec += 1000000;                                           \
+    }                                                                         \
+  } while (0)
+#endif
+
+static void
+format_elapsed_time (struct timeval *start, struct timeval *stop, char *elapsed)
+{
+/* well formatting elapsed time */
+    struct timeval diff;
+    int x;
+    int millis;
+    int secs;
+    int mins;
+    int hh;
+
+    timersub (stop, start, &diff);
+    millis = diff.tv_usec / 1000;
+    secs = diff.tv_sec % 60;
+    x = diff.tv_sec / 60;
+    mins = x % 60;
+    x /= 60;
+    hh = x;
+    sprintf (elapsed, "%d:%02d:%02d.%03d", hh, mins, secs, millis);
+}
+
+static void
+do_update_progress (int phase, sqlite3_int64 totlen, sqlite3_int64 donelen)
+{
+/* updating the "running wheel" */
+    char progress[64];
+    strcpy (progress, "........................................");
+    if (donelen)
+      {
+	  double percent = (double) donelen / (double) totlen;
+	  int tics = 40.0 * percent;
+	  int i;
+	  for (i = 0; i < tics; i++)
+	      progress[i] = 'X';
+      }
+    switch (phase % 8)
+      {
+      case 0:
+	  printf ("| %s\r", progress);
+	  break;
+      case 1:
+	  printf ("/ %s\r", progress);
+	  break;
+      case 2:
+	  printf ("- %s\r", progress);
+	  break;
+      case 3:
+	  printf ("\\ %s\r", progress);
+	  break;
+      case 4:
+	  printf ("| %s\r", progress);
+	  break;
+      case 5:
+	  printf ("/ %s\r", progress);
+	  break;
+      case 6:
+	  printf ("- %s\r", progress);
+	  break;
+      case 7:
+	  printf ("\\ %s\r", progress);
+	  break;
+      };
+    fflush (stdout);
+}
+
+static void
+do_help ()
+{
+/* printing the argument list */
+    fprintf (stderr, "\n\nusage: spatialite_xml_load ARGLIST\n");
+    fprintf (stderr,
+	     "==============================================================\n");
+    fprintf (stderr,
+	     "-h or --help                    print this help message\n");
+    fprintf (stderr, "-x or --xml-path pathname       the XML file path\n");
+    fprintf (stderr,
+	     "-d or --db-path     pathname    the SpatiaLite DB path\n\n");
+    fprintf (stderr, "you can specify the following options as well\n");
+    fprintf (stderr,
+	     "-cg or --collapsed-gml          collapsed GML Geometries\n");
+    fprintf (stderr,
+	     "-xl or --xlink-href             special GML xlink:href handling\n");
+    fprintf (stderr,
+	     "-nl or --nl-level      num      tree-level for table-names (dft: 0)\n");
+    fprintf (stderr,
+	     "-pl or --parent-levels num      how many ancestors for table-names (dft: -1)\n");
+    fprintf (stderr,
+	     "-jo or --journal-off            unsafe [but faster] mode\n");
+    fprintf (stderr,
+	     "-cs or --cache-size    num      DB cache size (how many pages)\n");
+    fprintf (stderr,
+	     "-m or --in-memory               using IN-MEMORY database\n");
+}
+
+int
+main (int argc, char *argv[])
+{
+/* the MAIN function mainly perform arguments checking */
+    sqlite3 *handle;
+    char *err_msg = NULL;
+    int ret;
+    int i;
+    int next_arg = ARG_NONE;
+    const char *xml_path = NULL;
+    const char *db_path = NULL;
+    int name_level = 0;
+    int parent_levels = -1;
+    int in_memory = 0;
+    int cache_size = 0;
+    int journal_off = 0;
+    int collapsed_gml = 0;
+    int xlink_href = 0;
+    int error = 0;
+    char Buff[BUFFSIZE];
+    int done = 0;
+    int len;
+    XML_Parser parser = NULL;
+    FILE *xml_file;
+    struct xml_params params;
+    void *cache;
+    struct timeval start;
+    struct timeval stop;
+    char elapsed[64];
+    int phase = 0;
+    int blklen = 0;
+    sqlite3_int64 totlen = 0;
+    sqlite3_int64 donelen = 0;
+
+    gettimeofday (&start, NULL);
+
+    params.filename = NULL;
+    params.db_handle = NULL;
+    params.journal_off = 0;
+    params.collapsed_gml = 0;
+    params.xlink_href = 0;
+    params.CharDataStep = 65536;
+    params.CharDataMax = params.CharDataStep;
+    params.CharData = malloc (params.CharDataStep);
+    params.CharDataLen = 0;
+    params.parse_error = 0;
+    params.db_error = 0;
+    params.first_tag = NULL;
+    params.last_tag = NULL;
+    params.sort_array = NULL;
+    params.count_array = 0;
+    params.first_table = NULL;
+    params.last_table = NULL;
+    params.stack = NULL;
+    params.CollapsingGML = 0;
+    params.CollapsedGML = NULL;
+    params.CollapsedGMLMarker = NULL;
+    params.treeLevel = -1;
+
+    for (i = 1; i < argc; i++)
+      {
+	  /* parsing the invocation arguments */
+	  if (next_arg != ARG_NONE)
+	    {
+		switch (next_arg)
+		  {
+		  case ARG_XML_PATH:
+		      xml_path = argv[i];
+		      break;
+		  case ARG_DB_PATH:
+		      db_path = argv[i];
+		      break;
+		  case ARG_CACHE_SIZE:
+		      cache_size = atoi (argv[i]);
+		      break;
+		  case ARG_NAME_LEVEL:
+		      name_level = atoi (argv[i]);
+		      break;
+		  case ARG_PARENT_LEVELS:
+		      parent_levels = atoi (argv[i]);
+		      break;
+		  };
+		next_arg = ARG_NONE;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "--help") == 0
+	      || strcmp (argv[i], "-h") == 0)
+	    {
+		do_help ();
+		return -1;
+	    }
+	  if (strcmp (argv[i], "-x") == 0)
+	    {
+		next_arg = ARG_XML_PATH;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "--xml-path") == 0)
+	    {
+		next_arg = ARG_XML_PATH;
+		continue;
+	    }
+	  if (strcmp (argv[i], "-d") == 0)
+	    {
+		next_arg = ARG_DB_PATH;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "--db-path") == 0)
+	    {
+		next_arg = ARG_DB_PATH;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "--cache-size") == 0
+	      || strcmp (argv[i], "-cs") == 0)
+	    {
+		next_arg = ARG_CACHE_SIZE;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "--name-level") == 0
+	      || strcmp (argv[i], "-nl") == 0)
+	    {
+		next_arg = ARG_NAME_LEVEL;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "--parent-levels") == 0
+	      || strcmp (argv[i], "-pl") == 0)
+	    {
+		next_arg = ARG_PARENT_LEVELS;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "-jo") == 0)
+	    {
+		journal_off = 1;
+		next_arg = ARG_NONE;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "--journal-off") == 0)
+	    {
+		journal_off = 1;
+		next_arg = ARG_NONE;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "-cg") == 0)
+	    {
+		collapsed_gml = 1;
+		next_arg = ARG_NONE;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "--collapsed-gml") == 0)
+	    {
+		collapsed_gml = 1;
+		next_arg = ARG_NONE;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "-xl") == 0)
+	    {
+		xlink_href = 1;
+		next_arg = ARG_NONE;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "--xlink-href") == 0)
+	    {
+		xlink_href = 1;
+		next_arg = ARG_NONE;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "-m") == 0)
+	    {
+		in_memory = 1;
+		next_arg = ARG_NONE;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "--in-memory") == 0)
+	    {
+		in_memory = 1;
+		next_arg = ARG_NONE;
+		continue;
+	    }
+	  fprintf (stderr, "unknown argument: %s\n", argv[i]);
+	  error = 1;
+      }
+    if (error)
+      {
+	  do_help ();
+	  return -1;
+      }
+
+/* checking the arguments */
+    if (!xml_path)
+      {
+	  fprintf (stderr,
+		   "did you forget setting the --xml-path argument ?\n");
+	  error = 1;
+      }
+    if (!db_path)
+      {
+	  fprintf (stderr, "did you forget setting the --db-path argument ?\n");
+	  error = 1;
+      }
+    if (error)
+      {
+	  do_help ();
+	  return -1;
+      }
+
+/* opening the DB */
+    if (in_memory)
+	cache_size = 0;
+    cache = spatialite_alloc_connection ();
+    open_db (db_path, &handle, cache_size, cache);
+    if (!handle)
+	return -1;
+
+    printf ("Target DB: %s\n", db_path);
+
+    if (in_memory)
+      {
+	  /* loading the DB in-memory */
+	  sqlite3 *mem_db_handle;
+	  sqlite3_backup *backup;
+	  int ret;
+	  ret =
+	      sqlite3_open_v2 (":memory:", &mem_db_handle,
+			       SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
+			       NULL);
+	  if (ret != SQLITE_OK)
+	    {
+		fprintf (stderr, "cannot open 'MEMORY-DB': %s\n",
+			 sqlite3_errmsg (mem_db_handle));
+		sqlite3_close (mem_db_handle);
+		return -1;
+	    }
+	  backup = sqlite3_backup_init (mem_db_handle, "main", handle, "main");
+	  if (!backup)
+	    {
+		fprintf (stderr, "cannot load 'MEMORY-DB'\n");
+		sqlite3_close (handle);
+		sqlite3_close (mem_db_handle);
+		return -1;
+	    }
+	  while (1)
+	    {
+		ret = sqlite3_backup_step (backup, 1024);
+		if (ret == SQLITE_DONE)
+		    break;
+	    }
+	  ret = sqlite3_backup_finish (backup);
+	  sqlite3_close (handle);
+	  handle = mem_db_handle;
+	  printf ("\nusing IN-MEMORY database\n");
+	  spatialite_cleanup_ex (cache);
+	  cache = spatialite_alloc_connection ();
+	  spatialite_init_ex (handle, cache, 0);
+      }
+
+    params.db_handle = handle;
+    params.journal_off = journal_off;
+    params.collapsed_gml = collapsed_gml;
+    params.xlink_href = xlink_href;
+    set_xml_filename (&params, xml_path);
+
+/* XML parsing - pass I */
+    xml_file = fopen (xml_path, "rb");
+    if (!xml_file)
+      {
+	  fprintf (stderr, "cannot open %s\n", xml_path);
+	  sqlite3_close (handle);
+	  return -1;
+      }
+    parser = XML_ParserCreate (NULL);
+    if (!parser)
+      {
+	  fprintf (stderr, "Couldn't allocate memory for parser\n");
+	  sqlite3_close (handle);
+	  return -1;
+      }
+
+    printf ("Input XML: %s\n", xml_path);
+
+    XML_SetUserData (parser, &params);
+/* XML parsing - pass I */
+    XML_SetElementHandler (parser, start_tag_1, end_tag_1);
+    XML_SetCharacterDataHandler (parser, xmlCharData);
+    blklen = 0;
+    while (!done)
+      {
+	  if (params.parse_error || params.db_error)
+	      goto parser_error1;
+	  len = fread (Buff, 1, BUFFSIZE, xml_file);
+	  totlen += len;
+	  blklen += len;
+	  if (blklen > BUFFSIZE * 100)
+	    {
+		do_update_progress (phase++, totlen, donelen);
+		blklen -= BUFFSIZE * 100;
+	    }
+	  if (ferror (xml_file))
+	    {
+		fprintf (stderr, "XML Read error\n");
+		goto parser_error1;
+	    }
+	  done = feof (xml_file);
+	  if (!XML_Parse (parser, Buff, len, done))
+	    {
+		fprintf (stderr, "Parse error at line %d:\n%s\n",
+			 (int) XML_GetCurrentLineNumber (parser),
+			 XML_ErrorString (XML_GetErrorCode (parser)));
+		goto parser_error1;
+	    }
+      }
+  parser_error1:
+    XML_ParserFree (parser);
+    fclose (xml_file);
+
+/* assigning the SQL table names for each XML Node class */
+    set_unique_names (&params, name_level, parent_levels);
+    set_table_names (&params);
+
+    if (params.journal_off)
+      {
+	  /* disabling the Journal File */
+	  ret =
+	      sqlite3_exec (params.db_handle, "PRAGMA journal_mode=OFF", NULL,
+			    NULL, &err_msg);
+	  if (ret != SQLITE_OK)
+	    {
+		fprintf (stderr, "JOURNAL MODE=OFF error: %s\n", err_msg);
+		sqlite3_free (err_msg);
+		goto abort;
+	    }
+	  ret =
+	      sqlite3_exec (params.db_handle, "PRAGMA synchronous=OFF", NULL,
+			    NULL, &err_msg);
+	  if (ret != SQLITE_OK)
+	    {
+		fprintf (stderr, "SYNCHRONOUS=OFF error: %s\n", err_msg);
+		sqlite3_free (err_msg);
+		goto abort;
+	    }
+      }
+
+/* starting a transaction */
+    ret = sqlite3_exec (params.db_handle, "BEGIN", NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "BEGIN error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  goto abort;
+      }
+
+/* creating/updating the SQL tables */
+    if (!prepare_sql_tables (&params))
+	goto abort;
+
+/* XML parsing - pass II */
+    done = 0;
+    if (params.CollapsedGMLMarker != NULL)
+      {
+	  sqlite3_free (params.CollapsedGMLMarker);
+	  params.CollapsedGMLMarker = NULL;
+      }
+    if (params.CollapsedGML != NULL)
+      {
+	  gmlDynBufferDestroy (params.CollapsedGML);
+	  params.CollapsedGML = NULL;
+      }
+    params.CollapsingGML = 0;
+
+    xml_file = fopen (xml_path, "rb");
+    if (!xml_file)
+      {
+	  fprintf (stderr, "cannot open %s\n", xml_path);
+	  sqlite3_close (handle);
+	  return -1;
+      }
+    parser = XML_ParserCreate (NULL);
+    if (!parser)
+      {
+	  fprintf (stderr, "Couldn't allocate memory for parser\n");
+	  sqlite3_close (handle);
+	  return -1;
+      }
+
+    XML_SetUserData (parser, &params);
+/* XML parsing - pass II */
+    XML_SetElementHandler (parser, start_tag_2, end_tag_2);
+    XML_SetCharacterDataHandler (parser, xmlCharData);
+    blklen = 0;
+    while (!done)
+      {
+	  if (params.parse_error || params.db_error)
+	      goto parser_error2;
+	  len = fread (Buff, 1, BUFFSIZE, xml_file);
+	  donelen += len;
+	  blklen += len;
+	  if (blklen > BUFFSIZE * 10)
+	    {
+		do_update_progress (phase++, totlen, donelen);
+		blklen -= BUFFSIZE * 10;
+	    }
+	  if (ferror (xml_file))
+	    {
+		fprintf (stderr, "XML Read error\n");
+		goto parser_error2;
+	    }
+	  done = feof (xml_file);
+	  if (!XML_Parse (parser, Buff, len, done))
+	    {
+		fprintf (stderr, "Parse error at line %d:\n%s\n",
+			 (int) XML_GetCurrentLineNumber (parser),
+			 XML_ErrorString (XML_GetErrorCode (parser)));
+		goto parser_error2;
+	    }
+      }
+  parser_error2:
+    XML_ParserFree (parser);
+    fclose (xml_file);
+
+/* committing the transaction */
+    ret = sqlite3_exec (params.db_handle, "COMMIT", NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "COMMIT error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+      }
+
+    gettimeofday (&stop, NULL);
+    format_elapsed_time (&start, &stop, elapsed);
+    printf ("Done - inserted/updated rows: %d [%s]\n\n",
+	    sqlite3_total_changes (params.db_handle), elapsed);
+
+  abort:
+    params_cleanup (&params);
+
+    if (in_memory)
+      {
+	  /* exporting the in-memory DB to filesystem */
+	  sqlite3 *disk_db_handle;
+	  sqlite3_backup *backup;
+	  int ret;
+	  printf ("\nexporting IN_MEMORY database ... wait please ...\n");
+	  ret =
+	      sqlite3_open_v2 (db_path, &disk_db_handle,
+			       SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
+			       NULL);
+	  if (ret != SQLITE_OK)
+	    {
+		fprintf (stderr, "cannot open '%s': %s\n", db_path,
+			 sqlite3_errmsg (disk_db_handle));
+		sqlite3_close (disk_db_handle);
+		return -1;
+	    }
+	  backup = sqlite3_backup_init (disk_db_handle, "main", handle, "main");
+	  if (!backup)
+	    {
+		fprintf (stderr, "Backup failure: 'MEMORY-DB' wasn't saved\n");
+		sqlite3_close (handle);
+		sqlite3_close (disk_db_handle);
+		return -1;
+	    }
+	  while (1)
+	    {
+		ret = sqlite3_backup_step (backup, 1024);
+		if (ret == SQLITE_DONE)
+		    break;
+	    }
+	  ret = sqlite3_backup_finish (backup);
+	  sqlite3_close (handle);
+	  handle = disk_db_handle;
+	  printf ("\tIN_MEMORY database succesfully exported\n");
+      }
+
+    sqlite3_close (handle);
+    spatialite_cleanup_ex (cache);
+    return 0;
+}
diff --git a/spatialite_xml_print.c b/spatialite_xml_print.c
new file mode 100644
index 0000000..8c155a0
--- /dev/null
+++ b/spatialite_xml_print.c
@@ -0,0 +1,1063 @@
+/* 
+/ spatialite_xml_print
+/
+/ a tool printing an XML file from SQLite tables
+/
+/ version 1.0, 2014 July 1
+/
+/ Author: Sandro Furieri a.furieri at lqt.it
+/
+/ Copyright (C) 2014  Alessandro Furieri
+/
+/    This program is free software: you can redistribute it and/or modify
+/    it under the terms of the GNU General Public License as published by
+/    the Free Software Foundation, either version 3 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 General Public License for more details.
+/
+/    You should have received a copy of the GNU General Public License
+/    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/
+*/
+
+#include <sys/time.h>
+
+#if defined(_WIN32) && !defined(__MINGW32__)
+/* MSVC strictly requires this include [off_t] */
+#include <sys/types.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "config.h"
+
+#ifdef SPATIALITE_AMALGAMATION
+#include <spatialite/sqlite3.h>
+#else
+#include <sqlite3.h>
+#endif
+#include <spatialite.h>
+#include <spatialite/gaiaaux.h>
+
+#define ARG_NONE	0
+#define ARG_XML_PATH	1
+#define ARG_DB_PATH	2
+#define ARG_CACHE_SIZE 3
+
+struct xml_attr
+{
+/* a struct wrapping an XML attribute */
+    char *attr_prefix;
+    char *attr_name;
+    struct xml_attr *next;
+};
+
+struct xml_node
+{
+/* a struct wrapping an XML node */
+    int level;
+    char *xml_prefix;
+    char *xml_tag;
+    char *table;
+    char *parent_table;
+    sqlite3_stmt *stmt;
+    struct xml_attr *first_attr;
+    struct xml_attr *last_attr;
+    struct xml_node *first;
+    struct xml_node *last;
+    struct xml_node *next;
+};
+
+static void
+do_destroy_node (struct xml_node *node)
+{
+/* memory cleanup - destroying an XML Node */
+    struct xml_attr *pa;
+    struct xml_attr *pan;
+    struct xml_node *pn;
+    struct xml_node *pnn;
+    if (node == NULL)
+	return;
+    if (node->xml_prefix != NULL)
+	free (node->xml_prefix);
+    if (node->xml_tag != NULL)
+	free (node->xml_tag);
+    if (node->table != NULL)
+	free (node->table);
+    if (node->parent_table != NULL)
+	free (node->parent_table);
+    if (node->stmt != NULL)
+	sqlite3_finalize (node->stmt);
+    pa = node->first_attr;
+    while (pa != NULL)
+      {
+	  pan = pa->next;
+	  if (pa->attr_prefix != NULL)
+	      free (pa->attr_prefix);
+	  if (pa->attr_name != NULL)
+	      free (pa->attr_name);
+	  free (pa);
+	  pa = pan;
+      }
+    pn = node->first;
+    while (pn != NULL)
+      {
+	  pnn = pn->next;
+	  do_destroy_node (pn);
+	  pn = pnn;
+      }
+    free (node);
+}
+
+static struct xml_node *
+alloc_xml_node (sqlite3 * sqlite, int level, const char *namespace,
+		const char *tag, const char *table, const char *parent)
+{
+/* creating an XML Node */
+    int len;
+    char *sql;
+    char *xtable;
+    int ret;
+    sqlite3_stmt *stmt;
+    struct xml_node *node = malloc (sizeof (struct xml_node));
+    node->level = level;
+    if (namespace == NULL)
+	node->xml_prefix = NULL;
+    else
+      {
+	  len = strlen (namespace);
+	  node->xml_prefix = malloc (len + 1);
+	  strcpy (node->xml_prefix, namespace);
+      }
+    len = strlen (tag);
+    node->xml_tag = malloc (len + 1);
+    strcpy (node->xml_tag, tag);
+    len = strlen (table);
+    node->table = malloc (len + 1);
+    strcpy (node->table, table);
+    if (parent == NULL)
+	node->parent_table = NULL;
+    else
+      {
+	  len = strlen (parent);
+	  node->parent_table = malloc (len + 1);
+	  strcpy (node->parent_table, parent);
+      }
+    xtable = gaiaDoubleQuotedSql (table);
+    if (parent == NULL)
+	sql = sqlite3_mprintf ("SELECT * FROM \"%s\"", xtable);
+    else
+	sql =
+	    sqlite3_mprintf ("SELECT * FROM \"%s\" WHERE parent_id = ?",
+			     xtable);
+    free (xtable);
+    node->stmt = NULL;
+    ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SELECT FROM xml_node error: %s\n",
+		   sqlite3_errmsg (sqlite));
+	  return NULL;
+      }
+    node->stmt = stmt;
+    node->first = NULL;
+    node->last = NULL;
+    node->first_attr = NULL;
+    node->last_attr = NULL;
+    node->next = NULL;
+    return node;
+}
+
+static struct xml_node *
+find_node_by_table (struct xml_node *node, const char *table)
+{
+/* recursively searching the XML Tree */
+    struct xml_node *pn;
+    struct xml_node *res;
+    if (strcasecmp (node->table, table) == 0)
+	return node;
+    pn = node->first;
+    while (pn != NULL)
+      {
+	  /* searching within children */
+	  res = find_node_by_table (pn, table);
+	  if (res != NULL)
+	      return res;
+	  pn = pn->next;
+      }
+    return NULL;
+}
+
+static int
+do_add_xml_node (sqlite3 * sqlite, struct xml_node *master, int level,
+		 const char *namespace, const char *tag, const char *table,
+		 const char *parent)
+{
+/* inserting a new node into the XML Tree */
+    struct xml_node *node;
+    struct xml_node *parent_node;
+    if (master == NULL)
+	return 0;
+    node = alloc_xml_node (sqlite, level, namespace, tag, table, parent);
+    parent_node = find_node_by_table (master, parent);
+    if (parent_node == NULL)
+	return 0;
+/* appending the child into the parent */
+    if (parent_node->first == NULL)
+	parent_node->first = node;
+    if (parent_node->last != NULL)
+	parent_node->last->next = node;
+    parent_node->last = node;
+    return 1;
+}
+
+static char *
+extract_attribute_prefix (struct xml_node *node, const char *reference)
+{
+    char *start;
+    int i;
+    if (node->xml_prefix == NULL)
+	start = sqlite3_mprintf ("<%s", node->xml_tag);
+    else
+	start = sqlite3_mprintf ("<%s:%s ", node->xml_prefix, node->xml_tag);
+
+    if (strncasecmp (start, reference, strlen (start)) == 0)
+      {
+	  int a = strlen (start);
+	  int b = -1;
+	  for (i = a; i < (int) strlen (reference); i++)
+	    {
+		if (*(reference + i) == ':')
+		  {
+		      b = i;
+		      break;
+		  }
+	    }
+	  sqlite3_free (start);
+	  if (b > a)
+	    {
+		int len = b - a;
+		char *prefix = malloc (len + 1);
+		memcpy (prefix, reference + a, len);
+		*(prefix + len) = '\0';
+		return prefix;
+	    }
+	  return NULL;
+      }
+    else
+	fprintf (stderr, "ERROR: invalid Attribute NameSpace\n");
+    sqlite3_free (start);
+    return NULL;
+}
+
+static void
+do_add_attribute (struct xml_node *node, char *prefix, const char *attribute)
+{
+/* creating and inserting a new XML attribute */
+    int len;
+    struct xml_attr *attr = malloc (sizeof (struct xml_attr));
+    attr->attr_prefix = prefix;
+    len = strlen (attribute);
+    attr->attr_name = malloc (len + 1);
+    strcpy (attr->attr_name, attribute);
+    attr->next = NULL;
+/* inserting into the XML Node */
+    if (node->first_attr == NULL)
+	node->first_attr = attr;
+    if (node->last_attr != NULL)
+	node->last_attr->next = attr;
+    node->last_attr = attr;
+}
+
+struct xml_node *
+do_build_master (sqlite3 * sqlite)
+{
+/* attempting to build the XML tree */
+    int ret;
+    const char *sql;
+    sqlite3_stmt *stmt = NULL;
+    struct xml_node *master = NULL;
+    struct xml_node *current = NULL;
+    int first = 1;
+
+/* extracting XML Nodes from MetaCatalog */
+    sql =
+	"SELECT tree_level, xml_tag_namespace, xml_tag_name, table_name, parent_table_name "
+	"FROM xml_metacatalog_tables " "ORDER BY tree_level, rowid";
+    ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SELECT FROM xml_metacatalog_tables error: %s\n",
+		   sqlite3_errmsg (sqlite));
+	  return NULL;
+      }
+    while (1)
+      {
+	  /* fetching the result set rows */
+	  ret = sqlite3_step (stmt);
+	  if (ret == SQLITE_DONE)
+	      break;		/* end of result set */
+	  if (ret == SQLITE_ROW)
+	    {
+		/* fetching a row */
+		const char *namespace = NULL;
+		const char *tag = NULL;
+		const char *table = NULL;
+		const char *parent = NULL;
+		int level = sqlite3_column_int (stmt, 0);
+		if (sqlite3_column_type (stmt, 1) == SQLITE_NULL)
+		    ;
+		else
+		    namespace = (const char *) sqlite3_column_text (stmt, 1);
+		if (sqlite3_column_type (stmt, 2) == SQLITE_NULL)
+		    ;
+		else
+		    tag = (const char *) sqlite3_column_text (stmt, 2);
+		if (sqlite3_column_type (stmt, 3) == SQLITE_NULL)
+		    ;
+		else
+		    table = (const char *) sqlite3_column_text (stmt, 3);
+		if (sqlite3_column_type (stmt, 4) == SQLITE_NULL)
+		    ;
+		else
+		    parent = (const char *) sqlite3_column_text (stmt, 4);
+		if (first)
+		  {
+		      /* this is the ROOT node */
+		      if (parent == NULL)
+			  master =
+			      alloc_xml_node (sqlite, level, namespace, tag,
+					      table, NULL);
+		      first = 0;
+		      if (master == NULL)
+			{
+			    fprintf (stderr,
+				     "ERROR: unable to build the XML Tree\n");
+			    goto error;
+			}
+		  }
+		else
+		  {
+		      if (!do_add_xml_node
+			  (sqlite, master, level, namespace, tag, table,
+			   parent))
+			{
+			    fprintf (stderr,
+				     "ERROR: unable to build the XML Tree\n");
+			    goto error;
+			}
+		  }
+	    }
+	  else
+	    {
+		fprintf (stderr, "SQL error: %s\n", sqlite3_errmsg (sqlite));
+		goto error;
+	    }
+      }
+    sqlite3_finalize (stmt);
+
+/* extract XML Attributes from MetaCatalog */
+    sql = "SELECT table_name, column_name, xml_reference "
+	"FROM xml_metacatalog_columns "
+	"WHERE Upper(column_name) NOT IN (Upper('node_id'), Upper('parent_id'), "
+	"Upper('node_value'), Upper('from_gml_geometry')) "
+	"ORDER BY table_name, ROWID";
+    ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SELECT FROM xml_metacatalog_columns error: %s\n",
+		   sqlite3_errmsg (sqlite));
+	  return NULL;
+      }
+    while (1)
+      {
+	  /* fetching the result set rows */
+	  ret = sqlite3_step (stmt);
+	  if (ret == SQLITE_DONE)
+	      break;		/* end of result set */
+	  if (ret == SQLITE_ROW)
+	    {
+		/* fetching a row */
+		const char *table =
+		    (const char *) sqlite3_column_text (stmt, 0);
+		const char *attribute =
+		    (const char *) sqlite3_column_text (stmt, 1);
+		const char *reference =
+		    (const char *) sqlite3_column_text (stmt, 2);
+		char *prefix = NULL;
+		if (current == NULL)
+		    current = find_node_by_table (master, table);
+		if (strcasecmp (current->table, table) != 0)
+		    current = find_node_by_table (master, table);
+		if (current == NULL || strcasecmp (current->table, table) != 0)
+		  {
+		      fprintf (stderr, "ERROR: unable to build the XML Tree\n");
+		      goto error;
+		  }
+		prefix = extract_attribute_prefix (current, reference);
+		do_add_attribute (current, prefix, attribute);
+	    }
+	  else
+	    {
+		fprintf (stderr, "SQL error: %s\n", sqlite3_errmsg (sqlite));
+		goto error;
+	    }
+      }
+    sqlite3_finalize (stmt);
+
+    return master;
+
+  error:
+    if (stmt != NULL)
+	sqlite3_finalize (stmt);
+    if (master != NULL)
+	do_destroy_node (master);
+    return NULL;
+}
+
+static char *
+clean_xml (const char *dirty)
+{
+/* well formatting an XML value */
+    char *clean;
+    char *out;
+    int i;
+    int extra = 0;
+    int len = strlen (dirty);
+    for (i = 0; i < len; i++)
+      {
+	  /* computing the required extra-length */
+	  switch (*(dirty + i))
+	    {
+	    case '&':
+		extra += 4;
+		break;
+	    case '<':
+		extra += 3;
+		break;
+	    case '>':
+		extra += 3;
+		break;
+	    case '\'':
+		extra += 5;
+		break;
+	    case '"':
+		extra += 5;
+		break;
+	    };
+      }
+    clean = malloc (len + extra + 1);
+    out = clean;
+    for (i = 0; i < len; i++)
+      {
+	  /* computing the required extra-length */
+	  switch (*(dirty + i))
+	    {
+	    case '&':
+		*out++ = '&';
+		*out++ = 'a';
+		*out++ = 'm';
+		*out++ = 'p';
+		*out++ = ';';
+		break;
+	    case '<':
+		*out++ = '&';
+		*out++ = 'l';
+		*out++ = 't';
+		*out++ = ';';
+		break;
+	    case '>':
+		*out++ = '&';
+		*out++ = 'g';
+		*out++ = 't';
+		*out++ = ';';
+		break;
+	    case '\'':
+		*out++ = '&';
+		*out++ = 'a';
+		*out++ = 'p';
+		*out++ = 'o';
+		*out++ = 's';
+		*out++ = ';';
+		break;
+	    case '"':
+		*out++ = '&';
+		*out++ = 'q';
+		*out++ = 'u';
+		*out++ = 'o';
+		*out++ = 't';
+		*out++ = ';';
+		break;
+	    default:
+		*out++ = *(dirty + i);
+		break;
+	    };
+      }
+    *out = '\0';
+    return clean;
+}
+
+static void
+do_print_xml_child (FILE * out, struct xml_node *node, sqlite3_int64 parent_id,
+		    sqlite3 * sqlite)
+{
+/* recursively printing the XML document - Child Node */
+    int ret;
+    char *indent;
+    int i;
+    sqlite3_stmt *stmt = node->stmt;
+    if (stmt == NULL)
+	return;
+
+    indent = malloc (node->level + 1);
+    for (i = 0; i < node->level; i++)
+	*(indent + i) = '\t';
+    *(indent + node->level) = '\0';
+
+    sqlite3_reset (stmt);
+    sqlite3_clear_bindings (stmt);
+    sqlite3_bind_int64 (stmt, 1, parent_id);
+    while (1)
+      {
+	  /* fetching the result set rows */
+	  ret = sqlite3_step (stmt);
+	  if (ret == SQLITE_DONE)
+	      break;		/* end of result set */
+	  if (ret == SQLITE_ROW)
+	    {
+		/* fetching a row */
+		struct xml_attr *attr;
+		struct xml_node *child;
+		char *xprefix;
+		char *xtag;
+		char *xvalue;
+		sqlite3_int64 node_id;
+		/* printing the XML Node start-tag */
+		if (node->xml_prefix == NULL)
+		  {
+		      xtag = clean_xml (node->xml_tag);
+		      fprintf (out, "%s<%s", indent, xtag);
+		      free (xtag);
+		  }
+		else
+		  {
+		      xprefix = clean_xml (node->xml_prefix);
+		      xtag = clean_xml (node->xml_tag);
+		      fprintf (out, "%s<%s:%s", indent, xprefix, xtag);
+		      free (xprefix);
+		      free (xtag);
+		  }
+		attr = node->first_attr;
+		while (attr != NULL)
+		  {
+		      /* printing all Node Attributes */
+		      const char *value = NULL;
+		      for (i = 0; i < sqlite3_column_count (stmt); i++)
+			{
+			    const char *column = sqlite3_column_name (stmt, i);
+			    if (strcasecmp (column, attr->attr_name) == 0)
+			      {
+				  if (sqlite3_column_type (stmt, i) ==
+				      SQLITE_NULL)
+				      ;
+				  else
+				      value =
+					  (const char *)
+					  sqlite3_column_text (stmt, i);
+				  break;
+			      }
+			}
+		      if (value == NULL)
+			{
+			    /* skipping NULL attributes */
+			    attr = attr->next;
+			    continue;
+			}
+		      if (attr->attr_prefix == NULL)
+			{
+			    xtag = clean_xml (attr->attr_name);
+			    xvalue = clean_xml (value);
+			    fprintf (out, " %s=\"%s\"", xtag, xvalue);
+			    free (xtag);
+			    free (xvalue);
+			}
+		      else
+			{
+			    xprefix = clean_xml (attr->attr_prefix);
+			    xtag = clean_xml (attr->attr_name);
+			    xvalue = clean_xml (value);
+			    fprintf (out, " %s:%s=\"%s\"", xprefix, xtag,
+				     xvalue);
+			    free (xprefix);
+			    free (xtag);
+			    free (xvalue);
+			}
+		      attr = attr->next;
+		  }
+		if (node->first == NULL)
+		  {
+		      /* we have no Childern nodes for sure */
+		      int from_gml_geometry = 0;
+		      const char *value = NULL;
+		      xvalue = NULL;
+		      for (i = 0; i < sqlite3_column_count (stmt); i++)
+			{
+			    const char *column = sqlite3_column_name (stmt, i);
+			    if (strcasecmp (column, "from_gml_geometry") == 0)
+				from_gml_geometry = 1;
+			    if (strcasecmp (column, "node_value") == 0)
+			      {
+				  if (sqlite3_column_type (stmt, i) !=
+				      SQLITE_NULL)
+				      value =
+					  (const char *)
+					  sqlite3_column_text (stmt, i);
+			      }
+			}
+		      if (value == NULL)
+			  fprintf (out, " />\n");
+		      else
+			{
+			    if (!from_gml_geometry)
+				xvalue = clean_xml (value);
+			    else
+				xvalue = (char *) value;
+			    if (node->xml_prefix == NULL)
+			      {
+				  xtag = clean_xml (node->xml_tag);
+				  fprintf (out, ">%s</%s>\n", xvalue, xtag);
+				  free (xtag);
+			      }
+			    else
+			      {
+				  xprefix = clean_xml (node->xml_prefix);
+				  xtag = clean_xml (node->xml_tag);
+				  fprintf (out, ">%s</%s:%s>\n", xvalue,
+					   xprefix, xtag);
+				  free (xprefix);
+				  free (xtag);
+			      }
+			    if (!from_gml_geometry)
+				free (xvalue);
+			}
+		  }
+		else
+		  {
+		      int i;
+		      fprintf (out, ">\n");
+		      node_id = 0;
+		      for (i = 0; i < sqlite3_column_count (stmt); i++)
+			{
+			    const char *column = sqlite3_column_name (stmt, i);
+			    if (strcasecmp (column, "node_id") == 0)
+			      {
+				  node_id = sqlite3_column_int64 (stmt, i);
+				  break;
+			      }
+			}
+		      child = node->first;
+		      while (child != NULL)
+			{
+			    /* recursively printing all Children nodes */
+			    do_print_xml_child (out, child, node_id, sqlite);
+			    child = child->next;
+			}
+		      /* printing the XML Node end-tag */
+		      if (node->xml_prefix == NULL)
+			{
+			    xtag = clean_xml (node->xml_tag);
+			    fprintf (out, "%s</%s>\n", indent, xtag);
+			    free (xtag);
+			}
+		      else
+			{
+			    xprefix = clean_xml (node->xml_prefix);
+			    xtag = clean_xml (node->xml_tag);
+			    fprintf (out, "%s</%s:%s>\n", indent, xprefix,
+				     xtag);
+			    free (xprefix);
+			    free (xtag);
+			}
+		  }
+	    }
+	  else
+	    {
+		fprintf (stderr, "SQL error: %s\n", sqlite3_errmsg (sqlite));
+		free (indent);
+		return;
+	    }
+      }
+    free (indent);
+}
+
+static void
+do_print_xml (FILE * out, struct xml_node *node, sqlite3 * sqlite)
+{
+/* printing the XML document - ROOT Node */
+    int ret;
+    int i;
+    sqlite3_stmt *stmt = node->stmt;
+    if (stmt == NULL)
+	return;
+
+    fprintf (out, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+
+    while (1)
+      {
+	  /* fetching the result set rows */
+	  ret = sqlite3_step (stmt);
+	  if (ret == SQLITE_DONE)
+	      break;		/* end of result set */
+	  if (ret == SQLITE_ROW)
+	    {
+		/* fetching a row */
+		struct xml_attr *attr;
+		struct xml_node *child;
+		char *xprefix;
+		char *xtag;
+		char *xvalue;
+		sqlite3_int64 node_id;
+		/* printing the XML Node start-tag */
+		if (node->xml_prefix == NULL)
+		  {
+		      xtag = clean_xml (node->xml_tag);
+		      fprintf (out, "<%s", xtag);
+		      free (xtag);
+		  }
+		else
+		  {
+		      xprefix = clean_xml (node->xml_prefix);
+		      xtag = clean_xml (node->xml_tag);
+		      fprintf (out, "<%s:%s", xprefix, xtag);
+		      free (xprefix);
+		      free (xtag);
+		  }
+		attr = node->first_attr;
+		while (attr != NULL)
+		  {
+		      /* printing all Node Attributes */
+		      const char *value = NULL;
+		      for (i = 0; i < sqlite3_column_count (stmt); i++)
+			{
+			    const char *column = sqlite3_column_name (stmt, i);
+			    if (strcasecmp (column, attr->attr_name) == 0)
+			      {
+				  if (sqlite3_column_type (stmt, i) ==
+				      SQLITE_NULL)
+				      ;
+				  else
+				      value =
+					  (const char *)
+					  sqlite3_column_text (stmt, i);
+				  break;
+			      }
+			}
+		      if (value == NULL)
+			{
+			    /* skipping NULL attributes */
+			    attr = attr->next;
+			    continue;
+			}
+		      if (attr->attr_prefix == NULL)
+			{
+			    xtag = clean_xml (attr->attr_name);
+			    xvalue = clean_xml (value);
+			    fprintf (out, " %s=\"%s\"", xtag, xvalue);
+			    free (xtag);
+			    free (xvalue);
+			}
+		      else
+			{
+			    xprefix = clean_xml (attr->attr_prefix);
+			    xtag = clean_xml (attr->attr_name);
+			    xvalue = clean_xml (value);
+			    fprintf (out, " %s:%s=\"%s\"", xprefix, xtag,
+				     xvalue);
+			    free (xprefix);
+			    free (xtag);
+			    free (xvalue);
+			}
+		      attr = attr->next;
+		  }
+		if (node->first == NULL)
+		  {
+		      /* we have no Childern nodes for sure */
+		      int from_gml_geometry = 0;
+		      const char *value = NULL;
+		      xvalue = NULL;
+		      for (i = 0; i < sqlite3_column_count (stmt); i++)
+			{
+			    const char *column = sqlite3_column_name (stmt, i);
+			    if (strcasecmp (column, "from_gml_geometry") == 0)
+				from_gml_geometry = 1;
+			    if (strcasecmp (column, "node_value") == 0)
+			      {
+				  if (sqlite3_column_type (stmt, i) !=
+				      SQLITE_NULL)
+				      value =
+					  (const char *)
+					  sqlite3_column_text (stmt, i);
+			      }
+			}
+		      if (value == NULL)
+			  fprintf (out, " />\n");
+		      else
+			{
+			    if (!from_gml_geometry)
+				xvalue = clean_xml (value);
+			    else
+				xvalue = (char *) value;
+			    if (node->xml_prefix == NULL)
+			      {
+				  xtag = clean_xml (node->xml_tag);
+				  fprintf (out, ">%s</%s>\n", xvalue, xtag);
+				  free (xtag);
+			      }
+			    else
+			      {
+				  xprefix = clean_xml (node->xml_prefix);
+				  xtag = clean_xml (node->xml_tag);
+				  fprintf (out, ">%s</%s:%s>\n", xvalue,
+					   xprefix, xtag);
+				  free (xprefix);
+				  free (xtag);
+			      }
+			    if (!from_gml_geometry)
+				free (xvalue);
+			}
+		  }
+		else
+		  {
+		      fprintf (out, ">\n");
+		      node_id = 0;
+		      for (i = 0; i < sqlite3_column_count (stmt); i++)
+			{
+			    const char *column = sqlite3_column_name (stmt, i);
+			    if (strcasecmp (column, "node_id") == 0)
+			      {
+				  node_id = sqlite3_column_int64 (stmt, i);
+				  break;
+			      }
+			}
+		      child = node->first;
+		      while (child != NULL)
+			{
+			    /* recursively printing all Children nodes */
+			    do_print_xml_child (out, child, node_id, sqlite);
+			    child = child->next;
+			}
+		      /* printing the XML Node end-tag */
+		      if (node->xml_prefix == NULL)
+			{
+			    xtag = clean_xml (node->xml_tag);
+			    fprintf (out, "</%s>\n", xtag);
+			    free (xtag);
+			}
+		      else
+			{
+			    xprefix = clean_xml (node->xml_prefix);
+			    xtag = clean_xml (node->xml_tag);
+			    fprintf (out, "</%s:%s>\n", xprefix, xtag);
+			    free (xprefix);
+			    free (xtag);
+			}
+		  }
+	    }
+	  else
+	    {
+		fprintf (stderr, "SQL error: %s\n", sqlite3_errmsg (sqlite));
+		return;
+	    }
+      }
+}
+
+static void
+open_db (const char *path, sqlite3 ** handle, int cache_size, void *cache)
+{
+/* opening the DB */
+    sqlite3 *db_handle;
+    int ret;
+    char sql[1024];
+
+    *handle = NULL;
+    printf ("SQLite version: %s\n", sqlite3_libversion ());
+    printf ("SpatiaLite version: %s\n", spatialite_version ());
+
+    ret = sqlite3_open_v2 (path, &db_handle, SQLITE_OPEN_READONLY, NULL);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "cannot open '%s': %s\n", path,
+		   sqlite3_errmsg (db_handle));
+	  sqlite3_close (db_handle);
+	  db_handle = NULL;
+	  return;
+      }
+    spatialite_init_ex (db_handle, cache, 0);
+
+    if (cache_size > 0)
+      {
+	  /* setting the CACHE-SIZE */
+	  sprintf (sql, "PRAGMA cache_size=%d", cache_size);
+	  sqlite3_exec (db_handle, sql, NULL, NULL, NULL);
+      }
+
+/* enabling PK/FK constraints */
+    sqlite3_exec (db_handle, "PRAGMA foreign_keys = 1", NULL, NULL, NULL);
+    *handle = db_handle;
+    return;
+}
+
+static void
+do_help ()
+{
+/* printing the argument list */
+    fprintf (stderr, "\n\nusage: spatialite_xml_printf ARGLIST\n");
+    fprintf (stderr,
+	     "==============================================================\n");
+    fprintf (stderr,
+	     "-h or --help                    print this help message\n");
+    fprintf (stderr,
+	     "-d or --db-path     pathname    the SpatiaLite DB [INPUT] path\n\n");
+    fprintf (stderr,
+	     "-x or --xml-path pathname       the XML file [OUUPUT] path\n");
+    fprintf (stderr,
+	     "-cs or --cache-size    num      DB cache size (how many pages)\n");
+    fprintf (stderr,
+	     "-m or --in-memory               using IN-MEMORY database\n");
+}
+
+int
+main (int argc, char *argv[])
+{
+/* the MAIN function mainly perform arguments checking */
+    sqlite3 *handle;
+    int i;
+    int next_arg = ARG_NONE;
+    const char *xml_path = NULL;
+    const char *db_path = NULL;
+    int cache_size = 0;
+    int error = 0;
+    void *cache;
+    struct xml_node *master = NULL;
+    FILE *out = NULL;
+
+    for (i = 1; i < argc; i++)
+      {
+	  /* parsing the invocation arguments */
+	  if (next_arg != ARG_NONE)
+	    {
+		switch (next_arg)
+		  {
+		  case ARG_XML_PATH:
+		      xml_path = argv[i];
+		      break;
+		  case ARG_DB_PATH:
+		      db_path = argv[i];
+		      break;
+		  case ARG_CACHE_SIZE:
+		      cache_size = atoi (argv[i]);
+		      break;
+		  };
+		next_arg = ARG_NONE;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "--help") == 0
+	      || strcmp (argv[i], "-h") == 0)
+	    {
+		do_help ();
+		return -1;
+	    }
+	  if (strcmp (argv[i], "-x") == 0)
+	    {
+		next_arg = ARG_XML_PATH;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "--xml-path") == 0)
+	    {
+		next_arg = ARG_XML_PATH;
+		continue;
+	    }
+	  if (strcmp (argv[i], "-d") == 0)
+	    {
+		next_arg = ARG_DB_PATH;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "--db-path") == 0)
+	    {
+		next_arg = ARG_DB_PATH;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "--cache-size") == 0
+	      || strcmp (argv[i], "-cs") == 0)
+	    {
+		next_arg = ARG_CACHE_SIZE;
+		continue;
+	    }
+	  fprintf (stderr, "unknown argument: %s\n", argv[i]);
+	  error = 1;
+      }
+    if (error)
+      {
+	  do_help ();
+	  return -1;
+      }
+
+/* checking the arguments */
+    if (!xml_path)
+      {
+	  fprintf (stderr,
+		   "did you forget setting the --xml-path argument ?\n");
+	  error = 1;
+      }
+    if (!db_path)
+      {
+	  fprintf (stderr, "did you forget setting the --db-path argument ?\n");
+	  error = 1;
+      }
+    if (error)
+      {
+	  do_help ();
+	  return -1;
+      }
+
+/* opening the DB */
+    cache = spatialite_alloc_connection ();
+    open_db (db_path, &handle, cache_size, cache);
+    if (!handle)
+	return -1;
+
+    printf ("Input DB: %s\n", db_path);
+
+/* preparing the XML Tree */
+    master = do_build_master (handle);
+    if (master == NULL)
+	goto error;
+
+/* opening the XML output file */
+    out = fopen (xml_path, "w");
+    if (out == NULL)
+      {
+	  fprintf (stderr,
+		   "Unable to create/open the output destination \"%s\"\n",
+		   xml_path);
+      }
+
+/* printing the output XML */
+    do_print_xml (out, master, handle);
+
+  error:
+    if (out != NULL)
+	fclose (out);
+    if (master != NULL)
+	do_destroy_node (master);
+    sqlite3_close (handle);
+    spatialite_cleanup_ex (cache);
+    return 0;
+}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/spatialite-tools.git



More information about the Pkg-grass-devel mailing list