The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
Changes 6172
MANIFEST 01
META.json 039
META.yml 1818
Makefile.PL 87
TinyXML.xs 619
lib/XML/TinyXML/Node.pm 56
lib/XML/TinyXML/NodeAttribute.pm 12
lib/XML/TinyXML/Selector/XPath/Axes.pm 12
lib/XML/TinyXML/Selector/XPath/Context.pm 13
lib/XML/TinyXML/Selector/XPath/Functions.pm 13
lib/XML/TinyXML/Selector/XPath.pm 1513
lib/XML/TinyXML/Selector.pm 12
lib/XML/TinyXML.pm 49
t/001_basic.t 11
t/002_import_export.t 13
t/003_special_chars.t 24
t/004_to_from_hash.t 01
t/006_xpath_unabbreviated.t 66
t/009_encoding.t 69
txml.c 119169
txml.h 017
typemap 680
23 files changed (This is a version diff) 325406
@@ -1,32 +1,50 @@
 Revision history for Perl extension TinyXML.
 
-0.01  Fri May 23 00:39:52 2008
-      - original version; created by h2xs 1.23 with options
-        -Oxan TinyXML linklist.h txml.h
-0.02  - switching from flock to ftrylockfile/funlockfile 
-        to ensure solaris compatibility
-0.03  - make the module to build properly on windows
-        (strtok_r doesn't exist on win32)
-      - added some documentation (more is still needed)
-0.04  - allow the module to be built and used by perl interpreters < 5.8.8
-      - some more documentation regarding the XML::TinyXML::Node object
-0.05  - updated documentation and implemented XML::TinyXML::addChildNode()
-0.06  - bugfix: typo in XML::TinyXML::Node.pm:109
-0.07  - correctly handle escaping/unescaping of xml special chars on 
-        import/export operations
-0.08  - bugfix : dexml() now works properly so special characters are now
-        handled correctly when importing xml data
-      - testunits now include escaping/unescaping-related checks
-0.09  - bugfix : xmlize() MUST ensure to null-terminate the escaped string
-        if the buffer had to be realloc'd
-0.10  - forcing prerequisite for perl >= 5.8
-      - introducing XmlGetAttributeByName() in the underlying C implementation
-      - fixed direct dumping on a file: XmlSave() dumped on a file only if it
-        already existed (blindly trying to create a backup copy). It now 
-        creates the file if not there (and backup it if already present)
-0.11  - fixed leaks in underlying XmlGetNode() and XmlSetNodePath()
-      - safety belt in XmlDumpBranch() to avoid accessing invalid memory
-        in some edge cases
+0.34  - The API is now 0-based (when dealing with arrays)
+      - fixed a bug in the parser triggered by extra spaces in start tags
+0.33  - allow to build even if iconv is missing. In which case encoding conversion functionalities will be disabled
+0.32  - fixed the 'Free to wrong pool' bug showing on multi-threaded perl when running on win32
+      - cleanings to suppress compiler warnings
+      - fixed compilation on some windows systems complaining about W32LockFile/W32UnlockFile redefinition
+      - fixed pod documentation for XML::TinyXML::Selector::XPath
+      - enforced 'use strict' and 'use warnings' on all perl modules
+0.31  - fixed a bug which caused the xpath selector to potentially return items 
+        in a random order when expanding a predicate (instead of returning them 
+        in the order of appearance in the document)
+0.30  - fixed an infinite loop introduced when adding the 'ignoreWhiteSpaces' flag
+      - expose a new accessor to directly construct an xml object from a file
+0.29  - reimplementing strcasestr() since it's not portable
+        (missing on solaris)
+      - fixed POD errors, warnings, formatting and a few doc typos
+0.28  - fixed testunits : added missing files to MANIFEST
+0.27  - fixed a namespace-related bug + minor cleanings
+0.26  - introduced 'ignoreBlanks' and 'ignoreWhiteSpaces' flags
+        (which affect both parsing and dumping behaviours)
+0.25  - reimplemented XmlDumpBranch optimizations through safer code
+0.24  - reverted XmlDumpBranch optimizations becuase 
+        memory corruption was caused by the new code
+0.23  - fixed a bug in hash-import routines
+        (0-values produced empty xml nodes)
+0.22  - introducing support for namespaces
+      - optimizations in the underlying C library
+0.21  - fixed a serious memory leak in the XS wrapper to XmlDump()
+      - updated more documentation
+0.20  - fixed a bug in Makefile.PL which was preventing it from being
+        properly built as port on freebsd
+0.19  - fixed MANIFEST to include encoding testunits
+      - setting doConversion when necessary also for generated documents
+        and not only when dumping an imported (and possibly modified) document
+      - documentation
+0.18  - fixed (hopefully) build on solaris
+0.17  - support encodings through iconv
+0.16  - bugfix in expression-parsing logic 
+        (used to parse nested boolean expressions within predicates)
+0.15  - full xpath support
+      - introducing XML::TinyXML::NodeAttribute API 
+        (as wrapper to the XmlNodeAttribute C structure)
+      - better testunits 
+0.14  - preliminary xpath (unabbreviated-only) implementation
+0.13  - switched to macro-based linklist implementation 
 0.12  - small improvements to the API (no changes...only extensions)
       - more testunits (and started rearranging them in multiple files)
       - by default, on export, empty nodes will use the shorter <node/> notation
@@ -34,37 +52,30 @@ Revision history for Perl extension TinyXML.
          as for defining encoding, whitespace handling and any other 
          optional behaviour which makes sense to take into account when 
          exporting)
-0.13  - switched to macro-based linklist implementation 
-0.14  - preliminary xpath (unabbreviated-only) implementation
-0.15  - full xpath support
-      - introducing XML::TinyXML::NodeAttribute API 
-        (as wrapper to the XmlNodeAttribute C structure)
-      - better testunits 
-0.16  - bugfix in expression-parsing logic 
-        (used to parse nested boolean expressions within predicates)
-0.17  - support encodings through iconv
-0.18  - fixed (hopefully) build on solaris
-0.19  - fixed MANIFEST to include encoding testunits
-      - setting doConversion when necessary also for generated documents
-        and not only when dumping an imported (and possibly modified) document
-      - documentation
-0.20  - fixed a bug in Makefile.PL which was preventing it from being
-        properly built as port on freebsd
-0.21  - fixed a serious memory leak in the XS wrapper to XmlDump()
-      - updated more documentation
-0.22  - introducing support for namespaces
-      - optimizations in the underlying C library
-0.23  - fixed a bug in hash-import routines
-        (0-values produced empty xml nodes)
-0.24  - reverted XmlDumpBranch optimizations becuase 
-        memory corruption was caused by the new code
-0.25  - reimplemented XmlDumpBranch optimizations through safer code
-0.26  - introduced 'ignoreBlanks' and 'ignoreWhiteSpaces' flags
-        (which affect both parsing and dumping behaviours)
-0.27  - fixed a namespace-related bug + minor cleanings
-0.28  - fixed testunits : added missing files to MANIFEST
-0.29  - reimplementing strcasestr() since it's not portable
-        (missing on solaris)
-      - fixed POD errors, warnings, formatting and a few doc typos
-0.30  - fixed an infinite loop introduced when adding the 'ignoreWhiteSpaces' flag
-      - expose a new accessor to directly construct an xml object from a file
+0.11  - fixed leaks in underlying XmlGetNode() and XmlSetNodePath()
+      - safety belt in XmlDumpBranch() to avoid accessing invalid memory
+        in some edge cases
+0.10  - forcing prerequisite for perl >= 5.8
+      - introducing XmlGetAttributeByName() in the underlying C implementation
+      - fixed direct dumping on a file: XmlSave() dumped on a file only if it
+        already existed (blindly trying to create a backup copy). It now 
+        creates the file if not there (and backup it if already present)
+0.09  - bugfix : xmlize() MUST ensure to null-terminate the escaped string
+        if the buffer had to be realloc'd
+0.08  - bugfix : dexml() now works properly so special characters are now
+        handled correctly when importing xml data
+      - testunits now include escaping/unescaping-related checks
+0.07  - correctly handle escaping/unescaping of xml special chars on 
+        import/export operations
+0.06  - bugfix: typo in XML::TinyXML::Node.pm:109
+0.05  - updated documentation and implemented XML::TinyXML::addChildNode()
+0.04  - allow the module to be built and used by perl interpreters < 5.8.8
+      - some more documentation regarding the XML::TinyXML::Node object
+0.03  - make the module to build properly on windows
+        (strtok_r doesn't exist on win32)
+      - added some documentation (more is still needed)
+0.02  - switching from flock to ftrylockfile/funlockfile 
+        to ensure solaris compatibility
+0.01  Fri May 23 00:39:52 2008
+      - original version; created by h2xs 1.23 with options
+        -Oxan TinyXML linklist.h txml.h
@@ -35,3 +35,4 @@ lib/XML/TinyXML/Selector.pm
 lib/XML/TinyXML.pm
 examples/sample1.pl
 META.yml                                 Module meta-data (added by MakeMaker)
+META.json                                Module JSON meta-data (added by MakeMaker)
@@ -0,0 +1,39 @@
+{
+   "abstract" : "Little and efficient Perl module to manage xml data. ",
+   "author" : [
+      "xant <xant@cpan.org>"
+   ],
+   "dynamic_config" : 1,
+   "generated_by" : "ExtUtils::MakeMaker version 6.72, CPAN::Meta::Converter version 2.120351",
+   "license" : [
+      "unknown"
+   ],
+   "meta-spec" : {
+      "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",
+      "version" : "2"
+   },
+   "name" : "XML-TinyXML",
+   "no_index" : {
+      "directory" : [
+         "t",
+         "inc"
+      ]
+   },
+   "prereqs" : {
+      "build" : {
+         "requires" : {
+            "ExtUtils::MakeMaker" : "0"
+         }
+      },
+      "configure" : {
+         "requires" : {
+            "ExtUtils::MakeMaker" : "0"
+         }
+      },
+      "runtime" : {
+         "requires" : {}
+      }
+   },
+   "release_status" : "stable",
+   "version" : "0.34"
+}
@@ -1,21 +1,21 @@
---- #YAML:1.0
-name:               XML-TinyXML
-version:            0.30
-abstract:           Little and efficient Perl module to manage xml data. 
+---
+abstract: 'Little and efficient Perl module to manage xml data. '
 author:
-    - xant <xant@cpan.org>
-license:            unknown
-distribution_type:  module
-configure_requires:
-    ExtUtils::MakeMaker:  0
+  - 'xant <xant@cpan.org>'
 build_requires:
-    ExtUtils::MakeMaker:  0
-requires:  {}
-no_index:
-    directory:
-        - t
-        - inc
-generated_by:       ExtUtils::MakeMaker version 6.56
+  ExtUtils::MakeMaker: 0
+configure_requires:
+  ExtUtils::MakeMaker: 0
+dynamic_config: 1
+generated_by: 'ExtUtils::MakeMaker version 6.72, CPAN::Meta::Converter version 2.120351'
+license: unknown
 meta-spec:
-    url:      http://module-build.sourceforge.net/META-spec-v1.4.html
-    version:  1.4
+  url: http://module-build.sourceforge.net/META-spec-v1.4.html
+  version: 1.4
+name: XML-TinyXML
+no_index:
+  directory:
+    - t
+    - inc
+requires: {}
+version: 0.34
@@ -30,12 +30,14 @@ elsif ($config{LIBS} !~ /-liconv/)
    if (linktest($config{LIBS}, $config{INC}))
    {
       $ok = 1;
-      print "ok (added -liconv)\n";
+      print "ok (added: '-DUSE_ICONV -liconv')\n";
    }
 }
 
 if ($ok)
 {
+   $config{CCFLAGS} = "$Config{ccflags} -DUSE_ICONV";
+
    print <<EOT;
 
 NOTE: If you have multiple iconv implementations installed, you might
@@ -48,11 +50,7 @@ EOT
 }
 else
 {
-   print "fail\n";
-
-   print "Failed to find iconv, please check your settings and re-run as:\n";
-   print "$^X Makefile.PL LIBS='-L/path/to/lib' INC='-I/path/to/include'\n";
-   exit 1;
+   print "Failed to find iconv, encoding functionalities will be disabled\n"
 }
 
 ###############################################################################
@@ -67,6 +65,7 @@ WriteMakefile(
     LIBS              => $config{LIBS},
     DEFINE            => '', # e.g., '-DHAVE_SOMETHING'
     INC               => "-I. $config{INC}",
+    CCFLAGS           => $config{CCFLAGS},
     OBJECT            => '$(O_FILES)', # link all the C files too
 );
 if  (eval {require ExtUtils::Constant; 1}) {
@@ -118,12 +117,12 @@ EOT
    {
       # It is admittedly a bit simplistic to simply concatenate all
       # flags, but it seems to work in most cases.
-      $compile = join ' ', $Config{cc}, $incs, $Config{ccflags},
+      $compile = join ' ', $Config{cc}, $incs, $Config{ccflags}, '-DUSE_ICONV',
 	  $Config{ldflags}, $libs;
    }
    else
    {
-      $compile = join ' ', $Config{cc}, $incs, $Config{ccflags}, $libs;
+      $compile = join ' ', $Config{cc}, $incs, $Config{ccflags}, '-DUSE_ICONV', $libs;
    }
 
    if (exists $config{verbose})
@@ -1,3 +1,7 @@
+
+#include <stdlib.h>
+static void (*std_free)(void *) = free;
+
 #include "EXTERN.h"
 #include "perl.h"
 #include "XSUB.h"
@@ -141,7 +145,7 @@ XmlDump(xml)
     dump = XmlDump(xml, &outlen);
     if (dump) {
         sv = newSVpv(dump, outlen);
-        free(dump);
+        std_free(dump);
     }
     RETVAL = sv;
     OUTPUT:
@@ -213,6 +217,9 @@ XmlSubstBranch(xml, index, newBranch)
     unsigned long    index
     XmlNode *newBranch
 
+int
+XmlHasIconv()
+
 MODULE = XML::TinyXML        PACKAGE = XmlNamespace
 
 XmlNamespace *
@@ -253,7 +260,7 @@ name(THIS, __value = NO_INIT)
     RETVAL = newSVpv(THIS->name, 0);
     if (items > 1) {
         if(THIS->name)
-        free(THIS->name);
+            free(THIS->name);
         THIS->name = __value;
     }
     OUTPUT:
@@ -268,7 +275,7 @@ uri(THIS, __value = NO_INIT)
     RETVAL = newSVpv(THIS->uri, 0);
     if (items > 1) {
         if(THIS->uri)
-        free(THIS->uri);
+            free(THIS->uri);
         THIS->uri = __value;
     }
     OUTPUT:
@@ -315,7 +322,7 @@ name(THIS, __value = NO_INIT)
     RETVAL = newSVpv(THIS->name, 0);
     if (items > 1) {
         if(THIS->name)
-        free(THIS->name);
+            free(THIS->name);
         THIS->name = __value;
     }
     OUTPUT:
@@ -330,7 +337,7 @@ value(THIS, __value = NO_INIT)
     RETVAL = newSVpv(THIS->value, 0);
     if (items > 1) {
         if(THIS->value)
-        free(THIS->value);
+            free(THIS->value);
         THIS->value = __value;
     }
     OUTPUT:
@@ -396,7 +403,7 @@ name(THIS, __value = NO_INIT)
     RETVAL = newSVpv(THIS->name, 0);
     if (items > 1) {
         if(THIS->name)
-        free(THIS->name);
+            free(THIS->name);
         THIS->name = __value;
     }
     OUTPUT:
@@ -588,3 +595,9 @@ ignoreWhiteSpaces(THIS, __value = NO_INIT)
     OUTPUT:
     RETVAL
 
+int
+hasIconv(THIS)
+    CODE:
+    RETVAL = XmlHasIconv();
+    OUTPUT:
+    RETVAL
@@ -65,7 +65,8 @@ Reference to the underlying XmlNodePtr object (which is a binding to the XmlNode
 package XML::TinyXML::Node;
 
 use strict;
-our $VERSION = '0.30';
+use warnings;
+our $VERSION = '0.34';
 
 =item * new ($entity, $value, $parent, %attrs)
 
@@ -298,7 +299,7 @@ Returns all attribute (array/arrayref of XML::TinyXML::NodeAttribute objects) fo
 sub getAttributes {
     my ($self) = shift;
     my @res;
-    for(my $i = 1; $i <= XML::TinyXML::XmlCountAttributes($self->{_node}); $i++) {
+    for(my $i = 0; $i < XML::TinyXML::XmlCountAttributes($self->{_node}); $i++) {
         push @res, XML::TinyXML::NodeAttribute->new(XML::TinyXML::XmlGetAttribute($self->{_node}, $i));
     }
     return wantarray?@res:\@res;
@@ -319,7 +320,7 @@ getAttributes() or getAttribute() instead.
 sub attributes {
     my ($self) = shift;
     my $res = {};
-    for(my $i = 1; $i <= XML::TinyXML::XmlCountAttributes($self->{_node}); $i++) {
+    for(my $i = 0; $i < XML::TinyXML::XmlCountAttributes($self->{_node}); $i++) {
         my $attr = XML::TinyXML::XmlGetAttribute($self->{_node}, $i);
         $res->{$attr->name} = $attr->value;
     }
@@ -367,7 +368,7 @@ Returns an array containing all actual children in the form of Xml::TinyXML::Nod
 sub children {
     my ($self) = @_;
     my @children;
-    for (my $i = 1; $i <= XML::TinyXML::XmlCountChildren($self->{_node}); $i++) {
+    for (my $i = 0; $i < XML::TinyXML::XmlCountChildren($self->{_node}); $i++) {
         push (@children, XML::TinyXML::Node->new(XML::TinyXML::XmlGetChildNode($self->{_node}, $i)));
     }
     return wantarray?@children:\@children;
@@ -412,7 +413,7 @@ Removes all children from this node
 =cut
 sub removeAllChildren {
     my ($self) = @_;
-    for (my $i = 1; $i <= $self->countChildren; $i++) {
+    for (my $i = 0; $i < $self->countChildren; $i++) {
         XML::TinyXML::XmlRemoveChildNode($self->{_node}, $i);
     }
 }
@@ -44,8 +44,9 @@ Reference to the underlying XmlNodeAttributePtr object (which is a binding to th
 package XML::TinyXML::NodeAttribute;
  
 use strict;
+use warnings;
 
-our $VERSION = "0.30";
+our $VERSION = "0.34";
 
 =item new ($attr)
 
@@ -1,9 +1,10 @@
 package XML::TinyXML::Selector::XPath::Axes;
 
 use strict;
+use warnings;
 use XML::TinyXML::NodeAttribute;
 
-our $VERSION = "0.30";
+our $VERSION = "0.34";
 
 sub child {
     my ($class, $context) = @_;
@@ -1,8 +1,10 @@
 # Internal use only
 package XML::TinyXML::Selector::XPath::Context;
 
+use strict;
+use warnings;
 
-our $VERSION = '0.30';
+our $VERSION = '0.34';
 
 our %Operators = (
  '+'   => sub {  $_[0] +  $_[1]  },
@@ -1,9 +1,11 @@
 # Internal use only
 package XML::TinyXML::Selector::XPath::Functions;
 
+use strict;
+use warnings;
 use POSIX qw(:sys_types_h);
 
-our $VERSION = "0.30";
+our $VERSION = "0.34";
 
 # NODE FUNCTIONS
 
@@ -55,6 +55,7 @@ XML::TinyXML::Selector::XPath - XPath-compliant selector for XML::TinyXML
 
   # refer to XPath documentation for further examples and details on the supported syntax:
   # ( http://www.w3.org/TR/xpath )
+
 =back
 
 =head1 DESCRIPTION
@@ -75,12 +76,13 @@ XPath-compliant selector for XML::TinyXML
 package XML::TinyXML::Selector::XPath;
 
 use strict;
+use warnings;
 use base qw(XML::TinyXML::Selector);
 use XML::TinyXML::Selector::XPath::Context;
 use XML::TinyXML::Selector::XPath::Functions;
 use XML::TinyXML::Selector::XPath::Axes;
 
-our $VERSION = '0.30';
+our $VERSION = '0.34';
 
 #our @ExprTokens = ('(', ')', '[', ']', '.', '..', '@', ',', '::');
 
@@ -323,7 +325,7 @@ sub _select_unabbreviated {
                 # save the actual context to ensure sending the correct context to all predicates
                 my $saved_context2 = $self->context;
                 foreach my $predicate_string (@predicates) {
-                    # using a temporary context while itereting over all predicates
+                    # using a temporary context while iterating over all predicates
                     my $tmpctx = XML::TinyXML::Selector::XPath::Context->new($self->{_xml});
                     $tmpctx->{items} = $saved_context2->items;
                     $self->{context} = $tmpctx;
@@ -333,29 +335,25 @@ sub _select_unabbreviated {
                         my ($p, $v) = split('=', $predicate_string);
                         $v =~ s/(^['"]|['"]$)//g if ($v); # XXX - unsafe dequoting ... think more to find a better regexp
                         my %uniq;
+                        my @nodepaths;
                         foreach my $node ($self->_select_unabbreviated($p ,1)) {
                             if ($node->type eq "ATTRIBUTE") {
-                                if ($v) {
-                                    $uniq{$node->node->path} = $node->node
-                                        if ($node->value eq $self->_unescape($v));
-                                } else {
-                                   $uniq{$node->node->path} = $node->node;
-                                }
+                                my $nodepath = $node->node->path;
+                                next if ($v && $node->value ne $self->_unescape($v));
+                                push(@nodepaths, $nodepath) if (!$uniq{$nodepath});
+                                $uniq{$nodepath} = $node->node
                             } else {
                                 my $parent = $node->parent;
                                 if ($parent) {
-                                    if ($v) {
-                                        $uniq{$parent->path} = $parent
-                                            if ($node->value eq $v);
-                                    } else {
-                                        $uniq{$parent->path} = $parent;
-                                    }
+                                    next if ($v && $node->value ne $v);
+                                    push(@nodepaths, $parent->path) if (!$uniq{$parent->path});
+                                    $uniq{$parent->path} = $parent
                                 } else {
                                     # TODO - Error Messages
                                 }
                             }
                         }
-                        push (@itemrefs, [ map { $uniq{$_} } keys %uniq ]);
+                        push (@itemrefs, [ map { $uniq{$_} } @nodepaths ]);
                     } else {
                         my $predicate = $self->_parse_predicate($predicate_string);
                         if ($predicate->{attr}) {
@@ -42,7 +42,8 @@ Selector base class
 package XML::TinyXML::Selector;
 
 use strict;
-our $VERSION = '0.30';
+use warnings;
+our $VERSION = '0.34';
 
 =item * new ($xml, $type, %args)
 
@@ -198,7 +198,7 @@ our @EXPORT = qw(
         XmlSetCurrentNamespace
 );
 
-our $VERSION = '0.30';
+our $VERSION = '0.34';
 
 sub AUTOLOAD {
     # This AUTOLOAD is used to 'autoload' constants from the constant()
@@ -424,7 +424,7 @@ sub loadHash {
         $self->addRootNode($root);
         $cur = $self->allowMultipleRootNodes
              ? $self->getNode($root)
-             : $self->getRootNode(1);
+             : $self->getRootNode(0);
     }
     return $cur->loadHash($hash);
 }
@@ -440,7 +440,7 @@ sub toHash {
     # only first branch will be parsed ... This means that if multiple root 
     # nodes are present (which is anyway not allowed by the xml spec), only 
     # the first one will be parsed and translated into an hashref
-    my $node = $self->getRootNode(1);
+    my $node = $self->getRootNode(0);
     return $node->toHash;
 }
 
@@ -589,7 +589,7 @@ In scalar context returns an arrayref.
 sub rootNodes {
     my ($self) = @_;
     my @nodes;
-    for (my $i = 1; $i <= XmlCountBranches($self->{_ctx}); $i++) {
+    for (my $i = 0; $i < XmlCountBranches($self->{_ctx}); $i++) {
         push (@nodes, XML::TinyXML::Node->new(XmlGetBranch($self->{_ctx}, $i)));
     }
     return wantarray?@nodes:\@nodes;
@@ -774,6 +774,11 @@ sub ignoreWhiteSpaces {
            : $self->{_ctx}->ignoreWhiteSpaces;
 }
 
+sub hasIconv {
+    my $self = shift;
+    return $self->{_ctx}->hasIconv;
+}
+
 sub DESTROY {
     my $self = shift;
     XmlDestroyContext($self->{_ctx})
@@ -56,7 +56,7 @@ is(ref($ref), "ARRAY");
 is(scalar(@$ref), 2);
 
 # can we remove an entire branch ?
-$txml->removeRootNode(1);
+$txml->removeRootNode(0);
 is($txml->countRootNodes, 1);
 
 # test switching ALLOW_MULTIPLE_ROOTNODES again
@@ -1,8 +1,10 @@
 
+use strict;
+
 use Test::More tests => 4;
 BEGIN { use_ok('XML::TinyXML') };
 
-$txml = XML::TinyXML->new();
+my $txml = XML::TinyXML->new();
 $txml->loadFile("./t/t.xml");
 my $out = $txml->dump;
 
@@ -1,9 +1,11 @@
+use strict;
 use Test::More tests => 3;
+
 BEGIN { use_ok('XML::TinyXML') };
 
-$txml = XML::TinyXML->new();
+my $txml = XML::TinyXML->new();
 $txml->loadBuffer("<node>Import&amp;special&quot;&lt;chars&gt;&#67;&#105;&#97;&#111;</node>");
-$node = $txml->getRootNode(1);
+my $node = $txml->getRootNode(0);
 ok ( $node->value eq "Import&special\"<chars>Ciao", "unescaping" );
 
 $txml = XML::TinyXML->new();
@@ -1,3 +1,4 @@
+use strict;
 use Test::More tests => 8;
 BEGIN { use_ok('XML::TinyXML') };
 
@@ -44,7 +44,7 @@ is ($set[0]->name, "foo");
 $selector->resetContext;
 @set = $selector->select("child::parent[child::blah='SECOND']");
 is (scalar(@set), 1);
-is ($set[0]->getChildNode(1)->name, "blah"); # tests both last selection and getChildNode
+is ($set[0]->getChildNode(0)->name, "blah"); # tests both last selection and getChildNode
 @set = $selector->select("attribute::*"); # reusing last context node
 is (scalar(@set), 1);
 is_deeply ([$set[0]->name, $set[0]->value], ['attr', 'val']); # ensure it's the expected attribute
@@ -83,22 +83,22 @@ is_deeply ([ $set[0]->name, $set[0]->value ], ['attr', 'val']); # ensure it's th
 $selector->resetContext;
 @set = $selector->select("child::parent[position()=2]");
 is (scalar(@set), 1);
-is ($set[0]->getChildNode(1)->name, "blah");
+is ($set[0]->getChildNode(0)->name, "blah");
 
 $selector->resetContext;
 @set = $selector->select("child::parent[position()=last()]");
 is (scalar(@set), 1);
-is ($set[0]->getChildNode(1)->name, "blah");
+is ($set[0]->getChildNode(0)->name, "blah");
 
 $selector->resetContext;
 @set = $selector->select("child::parent[position()=last()-1]");
 is (scalar(@set), 1);
-is ($set[0]->getChildNode(1)->name, "child1");
+is ($set[0]->getChildNode(0)->name, "child1");
 
 $selector->resetContext;
 @set = $selector->select("child::parent[position()=1+1]");
 is (scalar(@set), 1);
-is ($set[0]->getChildNode(1)->name, "blah");
+is ($set[0]->getChildNode(0)->name, "blah");
 
 # now check if using "2 mod 3" instead of "1+1" produces the same result
 $selector->resetContext;
@@ -108,7 +108,7 @@ is_deeply(\@set, \@set2);
 $selector->resetContext;
 @set = $selector->select("child::parent[position()>=1][position()=2]");
 is (scalar(@set), 1);
-is ($set[0]->getChildNode(1)->name, "blah");
+is ($set[0]->getChildNode(0)->name, "blah");
 
 $selector->resetContext;
 @set = $selector->select("descendant::*[attribute::attr]");
@@ -1,19 +1,22 @@
 
 use strict;
 use Test::More;
+use XML::TinyXML;
+use XML::TinyXML::Selector;
+
+my $txml;
 BEGIN {
-    if (eval "require Text::Iconv; 1") {
+    $txml = XML::TinyXML->new();
+    if (!$txml->hasIconv) {
+        plan skip_all => "Iconv functionalities disabled at compile time";
+    } elsif (eval "require Text::Iconv; 1") {
         plan tests => 2;
-    }
-    else {
+    } else {
         plan skip_all => "Text::Iconv not available";
     }
 }
 
-use XML::TinyXML;
-use XML::TinyXML::Selector;
 
-my $txml = XML::TinyXML->new();
 $txml->loadFile("./t/t.xml");
 
 my $utf8_output = $txml->dump;
@@ -8,7 +8,11 @@
 #include "txml.h"
 #include "string.h"
 #include "stdlib.h"
+#include "unistd.h"
+#include "ctype.h"
+#ifdef USE_ICONV
 #include "iconv.h"
+#endif
 #include "errno.h"
 
 #define XML_ELEMENT_NONE   0
@@ -76,7 +80,7 @@ dexmlize(char *string)
     char *unescaped = NULL;
 
     if (string) {
-        unescaped = calloc(1, len+1); // inlude null-byte
+        unescaped = (char *)calloc(1, len+1); // inlude null-byte
         for (i = 0; i < len; i++) {
             switch (string[i]) {
                 case '&':
@@ -138,7 +142,7 @@ xmlize(char *string)
     len = strlen(string);
     if (string) {
         bufsize = len+1;
-        escaped = calloc(1, bufsize); // inlude null-byte
+        escaped = (char *)calloc(1, bufsize); // inlude null-byte
         for (i = 0; i < len; i++) {
             switch (string[i]) {
                 case '&':
@@ -334,7 +338,7 @@ XmlCreateNode(char *name, char *value, XmlNode *parent)
     if(value && strlen(value) > 0)
         node->value = strdup(value);
     else
-        node->value = calloc(1, 1);
+        node->value = (char *)calloc(1, 1);
     return node;
 }
 
@@ -425,7 +429,7 @@ XmlUpdateKnownNamespaces(XmlNode *node)
     // first empty actual list
     if (!TAILQ_EMPTY(&node->knownNamespaces)) {
         XmlNamespaceSet *oldItem;
-        while(oldItem = TAILQ_FIRST(&node->knownNamespaces)) {
+        while((oldItem = TAILQ_FIRST(&node->knownNamespaces))) {
             TAILQ_REMOVE(&node->knownNamespaces, oldItem, next);
             free(oldItem);
         }
@@ -433,11 +437,11 @@ XmlUpdateKnownNamespaces(XmlNode *node)
 
     // than start populating the list with actual default namespace
     if (node->cns) {
-        newItem = calloc(1, sizeof(XmlNamespaceSet));
+        newItem = (XmlNamespaceSet *)calloc(1, sizeof(XmlNamespaceSet));
         newItem->ns = node->cns;
         TAILQ_INSERT_TAIL(&node->knownNamespaces, newItem, next);
     } else if (node->hns) {
-        newItem = calloc(1, sizeof(XmlNamespaceSet));
+        newItem = (XmlNamespaceSet *)calloc(1, sizeof(XmlNamespaceSet));
         newItem->ns = node->hns;
         TAILQ_INSERT_TAIL(&node->knownNamespaces, newItem, next);
     }
@@ -445,7 +449,7 @@ XmlUpdateKnownNamespaces(XmlNode *node)
     // add all namespaces defined by this node
     TAILQ_FOREACH(ns, &node->namespaces, list) {
         if (ns->name) { // skip an eventual default namespace since has been handled earlier
-            newItem = calloc(1, sizeof(XmlNamespaceSet));
+            newItem = (XmlNamespaceSet *)calloc(1, sizeof(XmlNamespaceSet));
             newItem->ns = ns;
             TAILQ_INSERT_TAIL(&node->knownNamespaces, newItem, next);
         }
@@ -457,7 +461,7 @@ XmlUpdateKnownNamespaces(XmlNode *node)
             XmlNamespaceSet *parentItem;
             TAILQ_FOREACH(parentItem, &node->parent->knownNamespaces, next) {
                 if (parentItem->ns->name) { // skip the default namespace
-                    newItem = calloc(1, sizeof(XmlNamespaceSet));
+                    newItem = (XmlNamespaceSet *)calloc(1, sizeof(XmlNamespaceSet));
                     newItem->ns = parentItem->ns;
                     TAILQ_INSERT_TAIL(&node->knownNamespaces, newItem, next);
                 }
@@ -465,7 +469,7 @@ XmlUpdateKnownNamespaces(XmlNode *node)
         } else { // this shouldn't happen until knownNamespaces is properly kept synchronized
             TAILQ_FOREACH(ns, &node->parent->namespaces, list) {
                 if (ns->name) { // skip the default namespace
-                    newItem = calloc(1, sizeof(XmlNamespaceSet));
+                    newItem = (XmlNamespaceSet *)calloc(1, sizeof(XmlNamespaceSet));
                     newItem->ns = ns;
                     TAILQ_INSERT_TAIL(&node->knownNamespaces, newItem, next);
                 }
@@ -508,7 +512,7 @@ XmlUpdateBranchNamespace(XmlNode *node, XmlNamespace *ns)
 
             newNS = XmlAddNamespace(node, node->ns->name, node->ns->uri);
             node->ns = newNS;
-            newItem = calloc(1, sizeof(XmlNamespaceSet));
+            newItem = (XmlNamespaceSet *)calloc(1, sizeof(XmlNamespaceSet));
             newItem->ns = newNS;
             TAILQ_INSERT_TAIL(&node->knownNamespaces, newItem, next);
             newAttr = malloc(strlen(newNS->name)+7); // prefix + xmlns + :
@@ -581,7 +585,7 @@ XmlAddAttribute(XmlNode *node, char *name, char *val)
     if(!name || !node)
         return XML_BADARGS;
 
-    attr = calloc(1, sizeof(XmlNodeAttribute));
+    attr = (XmlNodeAttribute *)calloc(1, sizeof(XmlNodeAttribute));
     attr->name = strdup(name);
     attr->value = val?strdup(val):strdup("");
     attr->node = node;
@@ -594,17 +598,16 @@ int
 XmlRemoveAttribute(XmlNode *node, unsigned long index)
 {
     XmlNodeAttribute *attr, *tmp;
-    int count = 1;
+    int count = 0;
 
     TAILQ_FOREACH_SAFE(attr, &node->attributes, list, tmp) {
-        if (count == index) {
+        if (count++ == index) {
             TAILQ_REMOVE(&node->attributes, attr, list);
             free(attr->name);
             free(attr->value);
             free(attr);
             return XML_NOERR;
         }
-        count++;
     }
     return XML_GENERIC_ERR;
 }
@@ -640,11 +643,10 @@ XmlNodeAttribute
 *XmlGetAttribute(XmlNode *node, unsigned long index)
 {
     XmlNodeAttribute *attr;
-    int count = 1;
+    int count = 0;
     TAILQ_FOREACH(attr, &node->attributes, list) {
-        if (count == index)
+        if (count++ == index)
             return attr;
-        count++;
     }
     return NULL;
 }
@@ -863,13 +865,11 @@ XmlParseBuffer(TXml *xml, char *buf)
 
 // skip tabs and new-lines
 #define SKIP_BLANKS(__p) \
-    while((*__p == '\t' || *__p == '\r' || *__p == '\n') && *__p != 0) __p++; \
-    if(*__p == 0) break;
+    while((*__p == '\t' || *__p == '\r' || *__p == '\n') && *__p != 0) __p++;
 
 // skip any kind of whitespace
 #define SKIP_WHITESPACES(__p) \
     SKIP_BLANKS(__p); \
-    if(*__p == 0) break;\
     while(*__p == ' ') {\
         __p++;\
         SKIP_BLANKS(__p);\
@@ -877,8 +877,7 @@ XmlParseBuffer(TXml *xml, char *buf)
     }
 
 #define ADVANCE_ELEMENT(__p) \
-    while(*__p != '>' && *__p != ' ' && *__p != '\t' && *__p != '\r' && *__p != '\n' && *__p != 0) __p++; \
-    if(*__p == 0) break;
+    while(*__p != '>' && *__p != ' ' && *__p != '\t' && *__p != '\r' && *__p != '\n' && *__p != 0) __p++;
 
 #define ADVANCE_TO_ATTR_VALUE(__p) \
     while(*__p != '=' && *__p != ' ' && *__p != '\t' && *__p != '\r' && *__p != '\n' && *__p != 0) __p++;\
@@ -951,7 +950,7 @@ XmlParseBuffer(TXml *xml, char *buf)
                 if(!p) {
                     /* XXX - TODO - This error condition must be handled asap */
                 }
-                comment = calloc(1, p-mark+1);
+                comment = (char *)calloc(1, p-mark+1);
                 if(!comment) {
                     err = XML_MEMORY_ERR;
                     goto _parser_err;
@@ -979,7 +978,7 @@ XmlParseBuffer(TXml *xml, char *buf)
                     if(!p) {
                         /* XXX - TODO - This error condition must be handled asap */
                     }
-                    cdata = calloc(1, p-mark+1);
+                    cdata = (char *)calloc(1, p-mark+1);
                     if(!cdata) {
                         err = XML_MEMORY_ERR;
                         goto _parser_err;
@@ -1000,7 +999,7 @@ XmlParseBuffer(TXml *xml, char *buf)
                 p = strstr(mark, "?>");
                 if(xml->head) // we are going to overwrite existing head (if any)
                     free(xml->head); /* XXX - should notify this behaviour? */
-                xml->head = calloc(1, p-mark+1);
+                xml->head = (char *)calloc(1, p-mark+1);
                 strncpy(xml->head, mark, p-mark);
                 encoding = strstr(xml->head, "encoding=");
                 if (encoding) {
@@ -1039,14 +1038,21 @@ XmlParseBuffer(TXml *xml, char *buf)
                 if(start == NULL)
                     return XML_MEMORY_ERR;
                 strncpy(start, mark, p-mark);
+
                 if(*p == '>' && *(p-1) == '/') {
                     start[p-mark-1] = 0;
                     state = XML_ELEMENT_UNIQUE;
-                }
-                else {
+                } else {
                     start[p-mark] = 0;
                 }
+
                 SKIP_WHITESPACES(p);
+                if(*p == '>' || (*p == '/' && *(p+1) == '>')) {
+                    if (*p == '/') {
+                        state = XML_ELEMENT_UNIQUE;
+                        p++;
+                    }
+                }
                 while(*p != '>' && *p != 0) {
                     mark = p;
                     ADVANCE_TO_ATTR_VALUE(p);
@@ -1151,6 +1157,74 @@ _parser_err:
     return err;
 }
 
+#ifdef WIN32
+//************************************************************************
+// BOOL W32LockFile (FILE* filestream)
+//
+// locks the specific file for exclusive access, nonblocking
+//
+// returns 0 on success
+//************************************************************************
+static BOOL
+W32LockFile (FILE* filestream)
+{
+    BOOL res = TRUE;
+    HANDLE hFile = INVALID_HANDLE_VALUE;
+    unsigned long size = 0;
+    int fd = 0;
+
+    // check params
+    if (!filestream)
+        goto __exit;
+
+    // get handle from stream
+    fd = _fileno (filestream);
+    hFile = (HANDLE)_get_osfhandle(fd);
+
+    // lock file until access is permitted
+    size = GetFileSize(hFile, NULL);
+    res = LockFile (hFile, 0, 0, size, 0);
+    if (res)
+        res = 0;
+__exit:
+    return res;
+}
+
+//************************************************************************
+// BOOL W32UnlockFile (FILE* filestream)
+//
+// unlocks the specific file locked by W32LockFile
+//
+// returns 0 on success
+//************************************************************************
+static BOOL
+W32UnlockFile (FILE* filestream)
+{
+    BOOL res = TRUE;
+    HANDLE hFile = INVALID_HANDLE_VALUE;
+    unsigned long size = 0;
+    int tries = 0;
+    int fd = 0;
+
+    // check params
+    if (!filestream)
+        goto __exit;
+
+    // get handle from stream
+    fd = _fileno (filestream);
+    hFile = (HANDLE)_get_osfhandle(fd);
+
+    // unlock
+    size = GetFileSize(hFile, NULL);
+    res = UnlockFile (hFile, 0, 0, size, 0);
+    if (res)
+        res = 0;
+
+__exit:
+    return res;
+}
+#endif // #ifdef WIN32
+
 static XmlErr
 XmlFileLock(FILE *file)
 {
@@ -1209,9 +1283,12 @@ XmlParseFile(TXml *xml, char *path)
     if(fileStat.st_size>0) {
         inFile = fopen(path, "r");
         if(inFile) {
+#ifdef USE_ICONV
             iconv_t ich;
-            size_t cb, ilen, olen;
-            char *out, *iconvIn, *iconvOut;
+            char *iconvIn, *iconvOut;
+#endif
+            char *out;
+            size_t rb, cb, ilen, olen;
             char *encoding_from = NULL;
 
             if(XmlFileLock(inFile) != XML_NOERR) {
@@ -1220,7 +1297,11 @@ XmlParseFile(TXml *xml, char *path)
             }
             olen = ilen = fileStat.st_size;
             buffer = (char *)malloc(ilen+1);
-            fread(buffer, 1, ilen, inFile);
+            rb = fread(buffer, 1, ilen, inFile);
+            if (ilen != rb) {
+                fprintf(stderr, "Can't read %s content", path);
+                return -1;
+            }
             buffer[ilen] = 0;
             switch(detect_encoding(buffer)) {
                 case ENCODING_UTF16LE:
@@ -1241,6 +1322,7 @@ XmlParseFile(TXml *xml, char *path)
                     break;
             }
             if (encoding_from) {
+#ifdef USE_ICONV
                 ich = iconv_open ("UTF-8", encoding_from);
                 if (ich == (iconv_t)(-1)) {
                     fprintf(stderr, "Can't init iconv: %s\n", strerror(errno));
@@ -1249,7 +1331,7 @@ XmlParseFile(TXml *xml, char *path)
                     fclose(inFile);
                     return -1;
                 }
-                out = calloc(1, olen);
+                out = (char *)calloc(1, olen);
                 iconvIn = buffer;
                 iconvOut = out;
                 cb = iconv(ich, &iconvIn, &ilen, &iconvOut, &olen);
@@ -1264,6 +1346,14 @@ XmlParseFile(TXml *xml, char *path)
                 free(buffer); // release initial buffer
                 buffer = out; // point to the converted buffer
                 iconv_close(ich);
+#else
+                fprintf(stderr, "Iconv missing: can't open file %s encoded in %s. Convert it to utf8 and try again\n",
+                        path, encoding_from);
+                free(buffer);
+                XmlFileUnlock(inFile);
+                fclose(inFile);
+                return -1;
+#endif
             }
             err = XmlParseBuffer(xml, buffer);
             free(buffer); // release either the initial or the converted buffer
@@ -1360,7 +1450,7 @@ XmlDumpBranch(TXml *xml, XmlNode *rNode, unsigned int depth)
     startOffset += nameLen;
     nAttrs = XmlCountAttributes(rNode);
     if(nAttrs>0) {
-        for(i = 1; i <= nAttrs; i++) {
+        for(i = 0; i < nAttrs; i++) {
             attr = XmlGetAttribute(rNode, i);
             if(attr) {
                 int anLen, avLen;
@@ -1466,7 +1556,9 @@ XmlDump(TXml *xml, int *outlen)
     XmlNode *rNode;
     char *branch;
     unsigned int i;
+#ifdef USE_ICONV
     int doConversion = 0;
+#endif
     char head[256]; // should be enough
     int hLen;
     unsigned int offset;
@@ -1495,25 +1587,48 @@ XmlDump(TXml *xml, int *outlen)
                     /* TODO - Error Messages */
                 } 
                 if (strncasecmp(encoding, xml->outputEncoding, end-encoding) != 0) {
+#ifdef USE_ICONV
                     snprintf(head, sizeof(head), "%sencoding=\"%s\"%s",
                         initial, xml->outputEncoding, ++end);
                     doConversion = 1;
+#else
+                    fprintf(stderr, "Iconv missing: will not convert output to %s\n", xml->outputEncoding);
+                    snprintf(head, sizeof(head), "%s", xml->head);
+#endif
                 } else {
                     snprintf(head, sizeof(head), "%s", xml->head);
                 }
+
             }
         } else {
-            if (xml->outputEncoding && strcasecmp(xml->outputEncoding, "utf-8") != 0)
+#ifdef USE_ICONV
+            if (xml->outputEncoding && strcasecmp(xml->outputEncoding, "utf-8") != 0) {
                 doConversion = 1;
+                fprintf(stderr, "Iconv missing: will not convert output to %s\n", xml->outputEncoding);
+            }
             snprintf(head, sizeof(head), "xml version=\"1.0\" encoding=\"%s\"", 
                 xml->outputEncoding?xml->outputEncoding:"utf-8");
+#else
+            if (xml->outputEncoding && strcasecmp(xml->outputEncoding, "utf-8") != 0) {
+                fprintf(stderr, "Iconv missing: will not convert output to %s\n", xml->outputEncoding);
+            }
+            snprintf(head, sizeof(head), "xml version=\"1.0\" encoding=\"utf-8\"");
+#endif
         }
         free(initial);
     } else {
-        if (xml->outputEncoding && strcasecmp(xml->outputEncoding, "utf-8") != 0)
+#ifdef USE_ICONV
+        if (xml->outputEncoding && strcasecmp(xml->outputEncoding, "utf-8") != 0) {
             doConversion = 1;
+        }
         snprintf(head, sizeof(head), "xml version=\"1.0\" encoding=\"%s\"", 
             xml->outputEncoding?xml->outputEncoding:"utf-8");
+#else
+        if (xml->outputEncoding && strcasecmp(xml->outputEncoding, "utf-8") != 0) {
+            fprintf(stderr, "Iconv missing: will not convert output to %s\n", xml->outputEncoding);
+        }
+        snprintf(head, sizeof(head), "xml version=\"1.0\" encoding=\"utf-8\"");
+#endif
     }
     hLen = strlen(head);
     dump = malloc(hLen+6);
@@ -1532,6 +1647,7 @@ XmlDump(TXml *xml, int *outlen)
     }
     if (outlen) // check if we need to report the output size
         *outlen = strlen(dump);
+#ifdef USE_ICONV
     if (doConversion) {
         iconv_t ich;
         size_t ilen, olen, cb;
@@ -1546,7 +1662,7 @@ XmlDump(TXml *xml, int *outlen)
         // we will update outlen later once iconv tell us the size
         if (outlen) 
             *outlen = olen;
-        out = calloc(1, olen);
+        out = (char *)calloc(1, olen);
         ich = iconv_open (xml->outputEncoding, xml->documentEncoding);
         if (ich == (iconv_t)(-1)) {
             free(dump);
@@ -1569,12 +1685,14 @@ XmlDump(TXml *xml, int *outlen)
         if (outlen) // update the outputsize if we have to
             *outlen -= olen;
     }
+#endif
     return(dump);
 }
 
 XmlErr
 XmlSave(TXml *xml, char *xmlFile)
 {
+    size_t rb;
     struct stat fileStat;
     FILE *saveFile = NULL;
     char *dump = NULL;
@@ -1596,7 +1714,11 @@ XmlSave(TXml *xml, char *xmlFile)
                 return XML_GENERIC_ERR;
             }
             backup = (char *)malloc(fileStat.st_size+1);
-            fread(backup, 1, fileStat.st_size, saveFile);
+            rb = fread(backup, 1, fileStat.st_size, saveFile);
+            if (rb != fileStat.st_size) {
+                fprintf(stderr, "Can't read %s content", xmlFile);
+                return -1;
+            }
             backup[fileStat.st_size] = 0;
             XmlFileUnlock(saveFile);
             fclose(saveFile);
@@ -1689,15 +1811,14 @@ XmlRemoveNode(TXml *xml, char *path)
 XmlErr
 XmlRemoveBranch(TXml *xml, unsigned long index)
 {
-    int count = 1;
+    int count = 0;
     XmlNode *branch, *tmp;
     TAILQ_FOREACH_SAFE(branch, &xml->rootElements, siblings, tmp) {
-        if (count == index) {
+        if (count++ == index) {
             TAILQ_REMOVE(&xml->rootElements, branch, siblings);
             XmlDestroyNode(branch);
             return XML_NOERR;
         }
-        count++;
     }
     return XML_GENERIC_ERR;
 }
@@ -1706,15 +1827,14 @@ XmlNode
 *XmlGetChildNode(XmlNode *node, unsigned long index)
 {
     XmlNode *child;
-    int count = 1;
+    int count = 0;
     if(!node)
         return NULL;
     TAILQ_FOREACH(child, &node->children, siblings) {
-        if (count == index) {
+        if (count++ == index) {
             return child;
             break;
         }
-        count++;
     }
     return NULL;
 }
@@ -1839,7 +1959,7 @@ XmlGetNode(TXml *xml, char *path)
             return NULL;
         }
 
-        for(i = 1; i <= XmlCountBranches(xml); i++) {
+        for(i = 0; i < XmlCountBranches(xml); i++) {
             wNode = XmlGetBranch(xml, i);
             if(strcmp(wNode->name, tag) == 0) {
                 cNode = wNode;
@@ -1853,7 +1973,7 @@ XmlGetNode(TXml *xml, char *path)
         tag = strtok(NULL, "/");
 #endif
     } else { // no multiple rootnodes
-        cNode = XmlGetBranch(xml, 1);
+        cNode = XmlGetBranch(xml, 0);
         // TODO - this could be done in a cleaner and more efficient way
         if (*walk != '/') {
             buff = malloc(strlen(walk)+2);
@@ -1896,13 +2016,12 @@ XmlNode
 *XmlGetBranch(TXml *xml, unsigned long index)
 {
     XmlNode *node;
-    int cnt = 1;
+    int cnt = 0;
     if(!xml)
         return NULL;
     TAILQ_FOREACH(node, &xml->rootElements, siblings) {
-        if (cnt == index)
+        if (cnt++ == index)
             return node;
-        cnt++;
     }
     return NULL;
 }
@@ -1911,14 +2030,13 @@ XmlErr
 XmlSubstBranch(TXml *xml, unsigned long index, XmlNode *newBranch)
 {
     XmlNode *branch, *tmp;
-    int cnt = 1;
+    int cnt = 0;
     TAILQ_FOREACH_SAFE(branch, &xml->rootElements, siblings, tmp) {
-        if (cnt == index) {
+        if (cnt++ == index) {
             TAILQ_INSERT_BEFORE(branch, newBranch, siblings);
             TAILQ_REMOVE(&xml->rootElements, branch, siblings);
             return XML_NOERR;
         }
-        cnt++;
     }
     return XML_LINKLIST_ERR;
 }
@@ -1926,7 +2044,7 @@ XmlSubstBranch(TXml *xml, unsigned long index, XmlNode *newBranch)
 XmlNamespace *
 XmlCreateNamespace(char *nsName, char *nsUri) {
     XmlNamespace *newNS;
-    newNS = calloc(1, sizeof(XmlNamespace));
+    newNS = (XmlNamespace *)calloc(1, sizeof(XmlNamespace));
     if (nsName)
         newNS->name = strdup(nsName);
     newNS->uri = strdup(nsUri);
@@ -2014,71 +2132,3 @@ XmlSetNodeNamespace(XmlNode *node, XmlNamespace *ns) {
     return XML_NOERR;
 }
 
-#ifdef WIN32
-//************************************************************************
-// BOOL W32LockFile (FILE* filestream)
-//
-// locks the specific file for exclusive access, nonblocking
-//
-// returns 0 on success
-//************************************************************************
-static BOOL
-W32LockFile (FILE* filestream)
-{
-    BOOL res = TRUE;
-    HANDLE hFile = INVALID_HANDLE_VALUE;
-    unsigned long size = 0;
-    int fd = 0;
-
-    // check params
-    if (!filestream)
-        goto __exit;
-
-    // get handle from stream
-    fd = _fileno (filestream);
-    hFile = (HANDLE)_get_osfhandle(fd);
-
-    // lock file until access is permitted
-    size = GetFileSize(hFile, NULL);
-    res = LockFile (hFile, 0, 0, size, 0);
-    if (res)
-        res = 0;
-__exit:
-    return res;
-}
-
-//************************************************************************
-// BOOL W32UnlockFile (FILE* filestream)
-//
-// unlocks the specific file locked by W32LockFile
-//
-// returns 0 on success
-//************************************************************************
-static BOOL
-W32UnlockFile (FILE* filestream)
-{
-    BOOL res = TRUE;
-    HANDLE hFile = INVALID_HANDLE_VALUE;
-    unsigned long size = 0;
-    int tries = 0;
-    int fd = 0;
-
-    // check params
-    if (!filestream)
-        goto __exit;
-
-    // get handle from stream
-    fd = _fileno (filestream);
-    hFile = (HANDLE)_get_osfhandle(fd);
-
-    // unlock
-    size = GetFileSize(hFile, NULL);
-    res = UnlockFile (hFile, 0, 0, size, 0);
-    if (res)
-        res = 0;
-
-__exit:
-    return res;
-}
-#endif // #ifdef WIN32
-
@@ -278,6 +278,14 @@ char *XmlDump(TXml *xml, int *outlen);
 */
 
 TXml *XmlCreateContext();
+
+
+/***
+    @brief Resets/cleans an existing context
+    @arg pointer to a valid xml context
+*/
+void XmlResetContext(TXml *xml);
+
 /***
     @brief release all resources associated to an xml context
     @arg pointer to a valid xml context
@@ -395,4 +403,13 @@ XmlErr XmlSetNodeCNamespace(XmlNode *node, XmlNamespace *ns);
 */ 
 XmlErr XmlSetCurrentNamespace(TXml *xml, char *nsuri);
 
+static inline int XmlHasIconv()
+{
+#ifdef USE_ICONV
+    return 1;
+#else
+    return 0;
+#endif
+}
+
 #endif
@@ -1,4 +1,3 @@
-FILE						T_OPAQUE_STRUCT
 TXml						T_OPAQUE_STRUCT
 TXml *						T_PTROBJ
 XmlNode						T_OPAQUE_STRUCT
@@ -8,74 +7,7 @@ XmlNodeAttribute *				T_PTROBJ
 XmlNamespace					T_OPAQUE_STRUCT
 XmlNamespace *					T_PTROBJ
 XmlErr						T_IV
-__int32_t					T_IV
-__mbstate_t					T_OPAQUE_STRUCT
-__mbstate_t *					T_PTROBJ
-__uint32_t					T_UV
-char * const *					T_PTROBJ
-const char *					T_PTROBJ
-const fpos_t *					T_PTROBJ
-const unsigned char *				T_PTROBJ
-const unsigned char **				T_PTROBJ
-char **						T_PTROBJ
-const void *					T_PTROBJ
-const wchar_t *					T_PTROBJ
-dev_t						T_IV
-div_t						T_OPAQUE_STRUCT
-div_t *						T_PTROBJ
-double [ ]					T_PTROBJ
-fbootstraptransfer_t				T_OPAQUE_STRUCT
-fbootstraptransfer_t *				T_PTROBJ
-fd_set						T_OPAQUE_STRUCT
-fd_set *					T_PTROBJ
-filesec_property_t				T_PTROBJ
-filesec_t					T_PTROBJ
-fpos_t						T_NV
-fpos_t ( * ) ( void *, fpos_t, int )		T_PTROBJ
-fpos_t *					T_PTROBJ
-fsignatures_t					T_OPAQUE_STRUCT
-fsignatures_t *					T_PTROBJ
-fstore_t					T_OPAQUE_STRUCT
-fstore_t *					T_PTROBJ
-id_t						T_UV
-int ( * ) ( const void *, const void * )	T_PTROBJ
-int ( * ) ( void * )				T_PTROBJ
-int ( * ) ( void *, char *, int )		T_PTROBJ
-int ( * ) ( void *, const char *, int )		T_PTROBJ
-int ( * ) ( void *, const void *, const void * )	T_PTROBJ
-int *						T_PTROBJ
-ldiv_t						T_OPAQUE_STRUCT
-ldiv_t *					T_PTROBJ
-lldiv_t						T_OPAQUE_STRUCT
-lldiv_t *					T_PTROBJ
-long *						T_PTROBJ
-long double					T_NV
-long long					T_NV
-mode_t						T_UV
-off_t						T_NV
-pid_t						T_IV
-pthread_mutex_t					T_OPAQUE_STRUCT
-siginfo_t					T_OPAQUE_STRUCT
-siginfo_t *					T_PTROBJ
-size_t *					T_PTROBJ
-struct __LinkedList *				T_PTROBJ
-struct __ListEntry *				T_PTROBJ
 struct __XmlNode *				T_PTROBJ
-struct __sFILEX *				T_PTROBJ
-struct __sbuf					T_OPAQUE_STRUCT
-struct rusage *					T_PTROBJ
-struct stat64 *					T_PTROBJ
-u_int32_t					T_UV
-uid_t						T_UV
-union sigval					T_OPAQUE_STRUCT
-unsigned *					T_PTROBJ
-unsigned long long				T_NV
-unsigned short *				T_PTROBJ
-unsigned short [ 3 ]				T_PTROBJ
-unsigned short [ 7 ]				T_PTROBJ
-va_list						T_PTROBJ
-void ( * ) ( void )				T_PTROBJ
-void ( * itemHandler ) ( void * item, unsigned long idx, void * user )	T_PTROBJ
 #############################################################################
 INPUT
 T_OPAQUE_STRUCT