The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
.gitignore 06
Build.PL 130
Changes 252564
MANIFEST 11
META.json 2725
META.yml 2013
Makefile.PL 114
README 11
lib/XML/Reader/Testcases.pm 3179
lib/XML/Reader.pm 24267
lib/XML/Reader_de.pod 699
lib/XML/Reader_fr.pod 7101
12 files changed (This is a version diff) 3551270
@@ -0,0 +1,6 @@
+Build
+MYMETA.*
+Makefile
+_build/
+blib/
+*.swp
@@ -1,13 +0,0 @@
-use strict;
-use warnings;
-use 5.008;
-
-use Module::Build;
-
-Module::Build->new(
-  module_name        => 'XML::Reader',
-  license            => 'perl',
-  configure_requires => { 'Module::Build' => 0.30 },
-  requires           => { 'Carp' => 0, 'Net::HTTP' => 0 },
-  dist_abstract      => 'Reading XML and providing path information based on a pull-parser',
-)->create_build_script;
@@ -1,254 +1,566 @@
 Revision history for XML-Reader
 
-0.01    22 Mar 2009
-        First version, released on an unsuspecting world.
-
-0.02    25 Mar 2009
-        add method level to indicate the nesting level of the XPath expression.
-
-0.03    26 Mar 2009
-        resolve circular reference in XML::TokeParser to avoid Memory leak
-
-0.04    27 Mar 2009
-        Replace XML::TokeParser by XML::Parser
-        add option {using => ...} and also add method prefix
-
-0.05    28 Mar 2009
-        fix a bug in option {using => ...}
-
-0.06    30 Mar 2009
-        re-order the output in XML::Reader->path
-
-0.07    02 Apr 2009
-        add a method XML::Reader->comment
-
-0.08    06 Apr 2009
-        update warranty
-
-0.09    06 Apr 2009
-        update licence
-        update Makefile.PL
-
-0.10    20 Jun 2009
-        Take out one test from t/0010-test.t
-
-0.11    24 Jun 2009
-        add method XML::Reader->is_init_attr() and XML::Reader->attr().
-        also, in case of {filter => 1}, undefine XML::Reader->is_start(),
-        XML::Reader->is_init_attr(), XML::Reader->is_end(), XML::Reader->comment().
-        Introduce {filter => 2} which removes the redundant start-line before
-        attributes.
-
-0.12    28 Jun 2009
-        add constructor XML::Reader->newhd, which is almost identical to
-        XML::Reader->new, except it defaults to {filter => 2}, whereas
-        the existing XML::Reader->new defaults to {filter => 0}
-
-0.13    28 Jun 2009
-        error correction in XML::Reader->is_init_attr()
-
-0.14    29 Jun 2009
-        add {filter => 3} and method $rdr->att_hash()
-
-0.15    29 Jun 2009
-        internal tuning
-
-0.16    30 Jun 2009
-        more internal tuning
-
-0.17    05 Jul 2009
-        even more internal tuning in handle_start() and in handle_end()
-
-0.18    30 Jul 2009
-        remove method XML::Reader->is_init_attr()
-        add processing instructions ("PI")
-        add option {parse_ct} for comments
-        add option {parse_pi} for processing-instructions
-        add option {filter => 4} and method XML::Reader->pyx() for PYX compliant data
-
-0.19    22 Aug 2009
-        remove option {filter => 0} and {filter => 1}
-        remove method new()
-        introducing "use Carp" and "croak"
-        clean up documentation and test cases
-
-0.20    25 Aug 2009
-        add method is_value()
-        add some example code to parse an XML file with XML::Reader
-
-0.21    12 Sep 2009
-        in method XML::Reader::DESTROY()
-          replace $self->{ExpatNB}->parse_done;
-          by      $self->{ExpatNB}->release;
-        in XML::Reader->new(): inject an {XR_debug} into $self->{ExpatNB}, if so requested
-          by $opt{debug}
-        add t/0030_test.t to test that XML::Reader does not leak memory
-        explain documentation (=item is_value) in more detail
-        translate POD-documentation into French: pod/XML-Reader-fr.pod
-        translate POD-documentation into German: pod/XML-Reader-de.pod
-        re-licence under the Artistic licence
-
-0.22    18 Sep 2009
-        Needed to bump up the version number due to wrong indexing of the
-        pod/XML-Reader-de/-fr.pod file in http://search.cpan.org/
-        Basically, I am renaming/relocating the two files
-        pod/XML-Reader-de.pod into lib/XML/Reader-de.pod
-        pod/XML-Reader-fr.pod into lib/XML/Reader-fr.pod
-
-0.23    19 Sep 2009
-        Needed to bump up the version number again due to wrong indexing.
-        Now I am introducing two new dummy *.pm files with their proper Packages
-        rename pod/XML-Reader-de.pod into lib/XML/Reader/German.pm
-        rename pod/XML-Reader-fr.pod into lib/XML/Reader/French.pm
-
-0.24    19 Sep 2009
-        Need to bump up the version number again, the indexing is still not working.
-        That's probably due to the missing =pod directive.
-        I have now added the =pod directive and I keep my fingers crossed
-
-0.25    20 Sep 2009
-        AGAIN AND AGAIN: Need to bump up the version number, the indexing is still not working.
-        renamed the two *.pm files into *.pod again.
-
-0.26    09 Oct 2009
-        Introduce a new function: 'slurp_xml' to slurp xml into an array-ref
-
-0.27    10 Oct 2009
-        Change the way 'slurp_xml' handles its parameters
-
-0.28    13 Oct 2009
-        Allow multiple roots in 'slurp_xml'
-        inject a "use 5.008" into Makefile.PL
-
-0.29    29 Oct 2009
-        Add {filter => 5}
-
-0.30    25 Jan 2010
-        include
-          translated POD-documentation into French: XML-Reader-fr.pod
-          translated POD-documentation into German: XML-Reader-de.pod
-        add Build.PL
-
-0.31    29 Jan 2010
-        - I am suddenly getting automated reports about test failures on systems where
-          XML::Parser has not been installed. To fix that problem, I have to add the
-          correct module dependency in Build.PL and in Makefile.PL.
-        - harmonize the version number in XML::Reader::Token with the version number
-          in XML::Reader
-
-0.32    17 Feb 2010
-        Fix a problem in Build.PL which had an incorrect version use 5.010; the correct
-        version is use 5.008;
-
-0.33    25 Apr 2010
-        For {filter => 5}:
-          - you can now have duplicate roots (which was not possible before)
-          - added a new function $self->rstem
-          - allow branch => '*' which will effectively collect all events and construct
-            a sub-tree in XML format, that XML-format has the correct translations
-              + < into &lt;
-              + > into &gt;
-              + & into &amp;
-              + ' into &apos;
-              + " into &quot;
-          - allow relative roots, such as 'tag1/tag2' or '//tag1/tag2'
-
-0.34    26 Apr 2010
-        For {filter => 5}: restrict { branch => '...' } to { branch => '*' } only
-
-0.35    28 Apr 2010
-        Relicencing under the "Artistic Licence 2.0"
-        Replace XML::Reader::newhd()
-             by XML::Reader::new()
-        Add option
-          {mode   => 'attr-bef-start' | 'attr-in-hash' | 'pyx' | 'branches'} as an alternative to the existing
-          {filter => 2|3|4|5}
-        Add an option {sepchar => 'xyz'} to XML::Reader->new
-        For {parse_pi => 1}, fix a bug with $rdr->dec_hash->{standalone}
-          (used to be '1' and '' which is false, 'yes' and 'no' is correct)
-        For {filter => 5}:
-          - function rstem() is redundant ==> replace function rstem() by path()
-          - fix a bug in functions is_text() / is_value()
-          - allow the writing of comments and PI if {branch => '*'} is selected
-
-0.36    01 June 2010
-        in case of {filter => 5}, make value() take over the role of rvalue()
-        Improve the content of the README file
-
-0.37    02 June 2010
-        The POD documentation has headers (=head1 and =head2) that are too
-        complicated, i.e. they contain characters like '(', ')' and '>'. This confuses
-        the POD Parser. This version simplifies the headers. (all 3 POD files are
-        affected: 'Reader.pm', 'Reader_fr.pod' and 'Reader_de.pod'
-
-0.38    18 Oct 2011
-        For PYX output, replace a single \ by a double \\ and replace tabs by a literal "\t"
-        Remove META.yml from MANIFEST
-
-0.39    28 Oct 2011
-        For filter => 5, add a new option '+' : {root => '/path1/path2', branch => '+'}
-          that allows to return an array of PYX-elements.
-        For filter => 5, existing option '*' : {root => '/path1/path2', branch => '*'}
-          replace reference to scalar in $self->{rvalue} by a plain scalar.
-        Remove deprecated functions newhd() and rstem()
-        Introduce XML::MinWriter
-
-0.40    24 Jun 2012
-        Allow XML::Reader to use the pure perl parser XML::Parsepp as an alternative to the
-        usual XML::Parser.
-
-0.41    28 Jul 2012
-        Change the way XML::Reader->new is used: (XML::Reader->new() now throws an
-        exception)
-        Old way: my $rdr = XML::Reader->new('test.xml') or die "Error: $!";
-        New way: my $rdr = eval{ XML::Reader->new('test.xml') } or die "Error: $@";
-        or new : my $rdr = XML::Reader->new('test.xml');
-
-0.42    30 Jul 2012
-        Add test file 0040_test_Module.t
-
-0.43    04 Aug 2012
-        Add a new option "dupatt" to XML::Reader->new() to allow for duplicate
-        attributes: (only valid when used in conjunction with "use XML::Reader qw(XML::Parsepp);")
-        my $rdr = XML::Reader->new('test.xml', {dupatt => '|'});
-        The concatenation string {dupatt => $str} is restricted to printable ascii excluding alphanumeric, " and '
-        Include explicit dependency on version 0.04 of XML::Parsepp
-
-0.44    04 Aug 2012
-        Allow { dupatt => '|' } with slurp_xml()
-        Allow { root => '/' } with { filter => 5 } / slurp_xml()
-
-0.45    05 Aug 2012
-        Refactor the code that allows { root => '/' } with { filter => 5 } / slurp_xml()
-
-0.46    06 Aug 2012
-        Error correction in the code that allows { root => '/' } with { filter => 5 } / slurp_xml()
-
-0.47    07 Aug 2012
-        Remove the dependencies on XML::Parser and XML::Parsepp and refactor/move the tests
-        out into XML::Reader::Testcases. The tests will later be called by the new modules
-        XML::Reader::PP and by XML::Reader::RS
-        Yet more error correction in the code that allows { root => '/' } with { filter => 5 }
-        / slurp_xml()
-
-0.48    09 Aug 2012
-        Refactor Test cases in XML::Reader::Testcases.
-
-0.49    09 Aug 2012
-        Make "use XML::Reader" (without any arguments) not load any of the modules "XML::Parser"
-        or "XML::Parsepp".
-
-0.50    08 Aug 2014
-        Add the possibility of reading http (using Net::HTTP)
-
-0.51    09 Aug 2014
-        Fix a typing error in the POD documentation:
-        "...an URL..." ==> "...a URL..."
-
-0.52    12 Aug 2014
-        I had forgotten to change another thing in the documentation (since 0.40, 24 Jun 2012):
-        "use XML::Reader;" should be spelled: "use XML::Reader qw(XML::Parser);"
-
-0.53    13 Aug 2014
-        This entry (0.53) only exists because I have forgotten to put in a changes entry
-        in the previous version (0.52)
+0.64 2014-08-24T18:23:41+01:00
+
+  [DOCUMENTATION]
+
+  - Add a .gitignore file (suggested by Gabor SZABO)
+
+  - Specify the actual version for the depenency Acme::HTTP in Makefile.PL
+
+0.63 2014-08-23T15:55:12+01:00
+
+  [DOCUMENTATION]
+
+  - Changelog dates are better written as YYYY.MM.DD and probably ordered in
+    the other, descending, direction (suggested by Gabor SZABO)
+    Remark: I have decided to follow the ISO 8601 standard at
+    http://www.w3.org/TR/NOTE-datetime
+
+0.62 2014-08-23T12:49:55+01:00
+
+  [DOCUMENTATION]
+
+  - Just use a Makefile.PL and not a Build.PL the latter does not have any
+    added value any more (suggested by Gabor SZABO)
+
+  - In Makefile.PL ==> meta files link to repository (suggested by Gabor SZABO)
+
+0.61 2014-08-22T10:41:06+01:00
+
+  [ENHANCEMENTS]
+
+  - Reflect latest changes in Acme::HTTP that make Acme::HTTP require
+    Net::HTTP/S::NB dynamically
+
+0.60 2014-08-22T08:39:19+01:00
+
+  [ENHANCEMENTS]
+
+  - Reflect latest changes in Acme::HTTP that returns a correctly blessed
+    Acme::HTTP object, also there is now more data abstraction in Acme::HTTP using
+    getter and setter subroutines
+
+0.59 2014-08-21T10:53:28+01:00
+
+  [ENHANCEMENTS]
+
+  - Reflect latest changes in Acme::HTTP that allows non-blocking read
+
+0.58 2014-08-19T09:25:15+01:00
+
+  [BUG FIX]
+
+  - Error correction in get_token(): Change the existing if-statement:
+    if (ref($self->NB_fh) eq 'Net::HTTP')
+    into
+    if (ref($self->NB_fh) eq 'Net::HTTP' or ref($self->NB_fh) eq 'Net::HTTPS')
+
+  [DOCUMENTATION]
+
+  - update the documentation and test cases
+
+0.57 2014-08-18T19:48:15+01:00
+
+  [ENHANCEMENTS]
+
+  - Allow a simple conditional [@attr="value"] inside a path expression,
+    for example { root => '/abs/sub1[@name="alpha"]/sub2',
+    branch => [ 'path3[@id="t1"]/path4', 'path5/path6/@code="data"' ] }
+
+0.56 2014-08-18T17:57:07+01:00
+
+  [ENHANCEMENTS]
+
+  - allow the branch section to contain sub-paths that don't start with slash
+    before: { root => '/abs/sub1/sub2', branch => [ '/path3/path4', '/path5/path6' ] }
+    after:  { root => '/abs/sub1/sub2', branch => [ 'path3/path4', 'path5/path6' ] }
+
+0.55 2014-08-18T13:24:47+01:00
+
+  [ENHANCEMENTS]
+
+  - replace the comple time "use Acme::HTTP" by the run time "require Acme::HTTP"
+
+0.54 2014-08-17T16:17:50+01:00
+
+  [ENHANCEMENTS]
+
+  - introduce Acme::HTTP
+
+0.53 2014-08-13T15:10:37+01:00
+
+  [DOCUMENTATION]
+
+  - This entry (0.53) only exists because I have forgotten to put in a changes entry
+    in the previous version (0.52)
+
+0.52 2014-08-12T16:02:50+01:00
+
+  [DOCUMENTATION]
+
+  - I had forgotten to change another thing in the documentation (since 0.40, 24 Jun 2012):
+    use XML::Reader; should be spelled: use XML::Reader qw(XML::Parser);
+
+0.51 2014-08-09T12:07:58+01:00
+
+  [BUG FIX]
+
+  - Fix a typing error in the POD documentation: "...an URL..." ==> "...a URL..."
+
+0.50 2014-08-08T17:50:47+01:00
+
+  [ENHANCEMENTS]
+
+  - Add the possibility of reading http (using Net::HTTP)
+
+0.49 2012-08-09T14:24:35+01:00
+
+  [ENHANCEMENTS]
+
+  - Make "use XML::Reader" (without any arguments) not load any of the modules "XML::Parser"
+    or "XML::Parsepp".
+
+0.48 2012-08-09T09:38:38+01:00
+
+  [DOCUMENTATION]
+
+  - Refactor Test cases in XML::Reader::Testcases.
+
+0.47 2012-08-07T17:12:59+01:00
+
+  [DOCUMENTATION]
+
+  - Remove the dependencies on XML::Parser and XML::Parsepp and refactor/move the tests
+    out into XML::Reader::Testcases. The tests will later be called by the new modules
+    XML::Reader::PP and by XML::Reader::RS
+
+  [BUG FIX]
+
+  - Yet more error correction in the code that allows { root => '/' }
+    with { filter => 5 } ==> slurp_xml()
+
+0.46 2012-08-06T10:06:18+01:00
+
+  [BUG FIX]
+
+  - Error correction in the code that allows { root => '/' } with { filter => 5 } / slurp_xml()
+
+0.45 2012-08-05T09:42:57+01:00
+
+  [REFACTORING]
+
+  - Refactor the code that allows { root => '/' } with { filter => 5 } / slurp_xml()
+
+0.44 2012-08-04T17:13:43+01:00
+
+  [ENHANCEMENTS]
+
+  - Allow { dupatt => '|' } with slurp_xml()
+
+  - Allow { root => '/' } with { filter => 5 } / slurp_xml()
+
+0.43 2012-08-04T12:21:12+01:00
+
+  [ENHANCEMENTS]
+
+  - Add a new option "dupatt" to XML::Reader->new() to allow for duplicate
+    attributes: (only valid when used in conjunction with "use XML::Reader qw(XML::Parsepp);")
+    my $rdr = XML::Reader->new('test.xml', {dupatt => '|'});
+
+  - The concatenation string {dupatt => $str} is restricted to printable ascii excluding alphanumeric, " and '
+
+  [DOCUMENTATION]
+
+  - Include explicit dependency on version 0.04 of XML::Parsepp
+
+0.42 2012-07-30T08:38:04+01:00
+
+  [DOCUMENTATION]
+
+  - Add test file 0040_test_Module.t
+
+0.41 2012-07-28T10:02:58+01:00
+
+  [ENHANCEMENTS]
+
+  - Change the way XML::Reader->new is used: (XML::Reader->new() now throws an
+    exception)
+    Old way: my $rdr = XML::Reader->new('test.xml') or die "Error: $!";
+    New way: my $rdr = eval{ XML::Reader->new('test.xml') } or die "Error: $@";
+    or new : my $rdr = XML::Reader->new('test.xml');
+
+0.40 2012-06-24T10:58:34+01:00
+
+  [ENHANCEMENTS]
+
+  - Allow XML::Reader to use the pure perl parser XML::Parsepp as an alternative to the
+    usual XML::Parser.
+
+0.39 2011-10-28T12:17:53+01:00
+
+  [ENHANCEMENTS]
+
+  - For filter => 5, add a new option '+' : {root => '/path1/path2', branch => '+'}
+    that allows to return an array of PYX-elements.
+
+  - For filter => 5, existing option '*' : {root => '/path1/path2', branch => '*'}
+    replace reference to scalar in $self->{rvalue} by a plain scalar.
+
+  [DEPRECATIONS]
+
+  - Remove deprecated functions newhd() and rstem()
+
+  [DOCUMENTATION]
+
+  - Introduce XML::MinWriter
+
+0.38 2011-10-18T13:22:28+01:00
+
+  [ENHANCEMENTS]
+
+  - For PYX output, replace a single \ by a double \\ and replace tabs by a literal "\t"
+
+  [DOCUMENTATION]
+
+  - Remove META.yml from MANIFEST
+
+0.37 2010-06-02T13:47:18+01:00
+
+  [DOCUMENTATION]
+
+  - The POD documentation has headers (=head1 and =head2) that are too
+    complicated, i.e. they contain characters like '(', ')' and '>'. This confuses
+    the POD Parser. This version simplifies the headers. (all 3 POD files are
+    affected: 'Reader.pm', 'Reader_fr.pod' and 'Reader_de.pod'
+
+0.36 2010-06-01T16:32:23+01:00
+
+  [ENHANCEMENTS]
+
+  - in case of {filter => 5}, make value() take over the role of rvalue()
+
+  [DOCUMENTATION]
+
+  - Improve the content of the README file
+
+0.35 2010-04-28T11:46:18+01:00
+
+  [ENHANCEMENTS]
+
+  - Replace XML::Reader::newhd() by XML::Reader::new()
+
+  - Add option {mode => 'attr-bef-start' | 'attr-in-hash' | 'pyx' | 'branches'}
+    as an alternative to the existing {filter => 2|3|4|5}
+
+  - Add an option {sepchar => 'xyz'} to XML::Reader->new
+
+  [BUG FIX]
+
+  - For {parse_pi => 1}, fix a bug with $rdr->dec_hash->{standalone}
+    used to be '1' and '' which is false, 'yes' and 'no' is correct
+
+  - For {filter => 5} function rstem() is redundant ==> replace function rstem() by path()
+
+  - Fix a bug in functions is_text() / is_value()
+
+  - Allow the writing of comments and PI if {branch => '*'} is selected
+
+  [DOCUMENTATION]
+
+  - Relicencing under the "Artistic Licence 2.0"
+
+0.34 2010-04-26T16:33:09+01:00
+
+  [ENHANCEMENTS]
+
+  - For {filter => 5}: restrict { branch => '...' } to { branch => '*' } only
+
+0.33 2010-04-25T09:15:52+01:00
+
+  [ENHANCEMENTS]
+
+  - For {filter => 5} you can now have duplicate roots (which was not possible before)
+
+  - added a new function $self->rstem
+
+  - allow relative roots, such as 'tag1/tag2' or '//tag1/tag2'
+
+  - allow branch => '*' which will effectively collect all events and construct
+    a sub-tree in XML format, that XML-format has the correct translations
+    char < into &lt;
+    char > into &gt;
+    char & into &amp;
+    char ' into &apos;
+    char " into &quot;
+
+
+0.32 2010-02-17T17:32:56+01:00
+
+  [BUG FIX]
+
+  - Fix a problem in Build.PL which had an incorrect version use 5.010; the correct
+    version is use 5.008;
+
+0.31 2010-01-29T08:52:34+01:00
+
+  [BUG FIX]
+
+  - I am suddenly getting automated reports about test failures on systems where
+    XML::Parser has not been installed. To fix that problem, I have to add the
+    correct module dependency in Build.PL and in Makefile.PL.
+
+  [DOCUMENTATION]
+
+  - harmonize the version number in XML::Reader::Token with the version number
+    in XML::Reader
+
+0.30 2010-01-25T11:00:16+01:00
+
+  [DOCUMENTATION]
+
+  - include
+    translated POD-documentation into French: XML-Reader-fr.pod
+    translated POD-documentation into German: XML-Reader-de.pod
+    add Build.PL
+
+0.29 2009-10-29T14:20:21+01:00
+
+  [ENHANCEMENTS]
+
+  - Add {filter => 5}
+
+0.28 2009-10-13T11:35:54+01:00
+
+  [ENHANCEMENTS]
+
+  - Allow multiple roots in 'slurp_xml'
+
+  [DOCUMENTATION]
+
+  - inject a "use 5.008" into Makefile.PL
+
+0.27 2009-10-10T14:24:33+01:00
+
+  [ENHANCEMENTS]
+
+  - Change the way 'slurp_xml' handles its parameters
+
+0.26 2009-10-09T11:41:32+01:00
+
+  [ENHANCEMENTS]
+
+  - Introduce a new function: 'slurp_xml' to slurp xml into an array-ref
+
+0.25 2009-09-20T17:34:28+01:00
+
+  [DOCUMENTATION]
+
+  - Need to bump up the version number, the indexing is still not working.
+    renamed the two *.pm files into *.pod again.
+
+0.24 2009-09-19T08:29:45+01:00
+
+  [DOCUMENTATION]
+
+  - Need to bump up the version number again, the indexing is still not working.
+    That's probably due to the missing =pod directive.
+    I have now added the =pod directive and I keep my fingers crossed
+
+0.23 2009-09-19T08:41:26+01:00
+
+  [DOCUMENTATION]
+
+  - Needed to bump up the version number again due to wrong indexing.
+    Now I am introducing two new dummy *.pm files with their proper Packages
+    rename pod/XML-Reader-de.pod into lib/XML/Reader/German.pm
+    rename pod/XML-Reader-fr.pod into lib/XML/Reader/French.pm
+
+0.22 2009-09-18T09:42:04+01:00
+
+  [DOCUMENTATION]
+
+  - Needed to bump up the version number due to wrong indexing of the
+    pod/XML-Reader-de/-fr.pod file in http://search.cpan.org/
+    Basically, I am renaming/relocating the two files
+    pod/XML-Reader-de.pod into lib/XML/Reader-de.pod
+    pod/XML-Reader-fr.pod into lib/XML/Reader-fr.pod
+
+0.21 2009-09-12T11:16:08+01:00
+
+  [BUG FIX]
+
+  - in method XML::Reader::DESTROY()
+    replace $self->{ExpatNB}->parse_done;
+    by      $self->{ExpatNB}->release;
+
+  [DOCUMENTATION]
+
+  - in XML::Reader->new(): inject an {XR_debug} into $self->{ExpatNB}, if so requested
+    by $opt{debug}
+
+  - add t/0030_test.t to test that XML::Reader does not leak memory
+
+  - explain documentation (=item is_value) in more detail
+
+  - translate POD-documentation into French: pod/XML-Reader-fr.pod
+    translate POD-documentation into German: pod/XML-Reader-de.pod
+
+  - re-licence under the Artistic licence
+
+0.20 2009-08-25T12:05:55+01:00
+
+  [ENHANCEMENTS]
+
+  - add method is_value()
+
+  [DOCUMENTATION]
+
+  - add some example code to parse an XML file with XML::Reader
+
+0.19 2009-08-22T10:59:28+01:00
+
+  [DEPRECATIONS]
+
+  - remove option {filter => 0} and {filter => 1}
+
+  - remove method new()
+
+  [ENHANCEMENTS]
+
+  - introducing "use Carp" and "croak"
+
+  [DOCUMENTATION]
+
+  - clean up documentation and test cases
+
+0.18 2009-07-30T11:30:05+01:00
+
+  [DEPRECATIONS]
+
+  - remove method XML::Reader->is_init_attr()
+
+  [ENHANCEMENTS]
+
+  - add processing instructions ("PI")
+
+  - add option {parse_ct} for comments
+
+  - add option {parse_pi} for processing-instructions
+
+  - add option {filter => 4} and method XML::Reader->pyx() for PYX compliant data
+
+0.17 2009-07-05T16:09:06+01:00
+
+  [REFACTORING]
+
+  - even more internal tuning in handle_start() and in handle_end()
+
+0.16 2009-06-30T08:26:47+01:00
+
+  [REFACTORING]
+
+  - more internal tuning
+
+0.15 2009-06-29T08:47:08+01:00
+
+  [REFACTORING]
+
+  - internal tuning
+
+0.14 2009-06-29T14:30:23+01:00
+
+  [ENHANCEMENTS]
+
+  - add {filter => 3} and method $rdr->att_hash()
+
+0.13 2009-06-28T12:26:39+01:00
+
+  [BUG FIX]
+
+  - error correction in XML::Reader->is_init_attr()
+
+0.12 2009-06-28T13:02:58+01:00
+
+  [ENHANCEMENTS]
+
+  - add constructor XML::Reader->newhd, which is almost identical to
+    XML::Reader->new, except it defaults to {filter => 2}, whereas
+    the existing XML::Reader->new defaults to {filter => 0}
+
+0.11 2009-06-24T08:51:28+01:00
+
+  [ENHANCEMENTS]
+
+  - add method XML::Reader->is_init_attr() and XML::Reader->attr().
+
+  - in case of {filter => 1}, undefine XML::Reader->is_start(),
+    XML::Reader->is_init_attr(), XML::Reader->is_end(), XML::Reader->comment().
+
+  - Introduce {filter => 2} which removes the redundant start-line before
+    attributes.
+
+0.10 2009-06-20T08:45:05+01:00
+
+  [DOCUMENTATION]
+
+  - Take out one test from t/0010-test.t
+
+0.09 2009-04-06T15:28:58+01:00
+
+  [DOCUMENTATION]
+
+  - update licence
+    update Makefile.PL
+
+0.08 2009-04-06T17:34:07+01:00
+
+  [DOCUMENTATION]
+
+  - update warranty
+
+0.07 2009-04-02T08:39:53+01:00
+
+  [ENHANCEMENTS]
+
+  - add a method XML::Reader->comment
+
+0.06 2009-03-30T08:24:50+01:00
+
+  [ENHANCEMENTS]
+
+  - re-order the output in XML::Reader->path
+
+0.05 2009-03-28T17:25:28+01:00
+
+  [BUG FIX]
+
+  - fix a bug in option {using => ...}
+
+0.04 2009-03-27T15:04:18+01:00
+
+  [ENHANCEMENTS]
+
+  - Replace XML::TokeParser by XML::Parser
+
+  - add option {using => ...}
+
+  - add method prefix
+
+0.03 2009-03-26T15:27:59+01:00
+
+  [BUG FIX]
+
+  - resolve circular reference in XML::TokeParser to avoid Memory leak
+
+0.02 2009-03-25T17:31:44+01:00
+
+  [ENHANCEMENTS]
+
+  - add method level to indicate the nesting level of the XPath expression.
+
+0.01 2009-03-22T12:30:17+01:00
+
+  [ENHANCEMENTS]
+
+  - First version, released on an unsuspecting world.
@@ -1,8 +1,8 @@
+.gitignore
 Changes
 MANIFEST
 LICENCE
 Makefile.PL
-Build.PL
 README
 lib/XML/Reader.pm
 lib/XML/Reader_fr.pod
@@ -1,8 +1,10 @@
 {
-   "abstract" : "Reading XML and providing path information based on a pull-parser",
-   "author" : [],
+   "abstract" : "Reading XML and providing path information based on a pull-parser.",
+   "author" : [
+      "Klaus Eichner <klaus03@gmail.com>"
+   ],
    "dynamic_config" : 1,
-   "generated_by" : "Module::Build version 0.4205",
+   "generated_by" : "ExtUtils::MakeMaker version 6.98, CPAN::Meta::Converter version 2.141170",
    "license" : [
       "perl_5"
    ],
@@ -11,41 +13,37 @@
       "version" : "2"
    },
    "name" : "XML-Reader",
+   "no_index" : {
+      "directory" : [
+         "t",
+         "inc"
+      ]
+   },
    "prereqs" : {
+      "build" : {
+         "requires" : {
+            "ExtUtils::MakeMaker" : "0"
+         }
+      },
       "configure" : {
          "requires" : {
-            "Module::Build" : "0.3"
+            "ExtUtils::MakeMaker" : "0"
          }
       },
       "runtime" : {
          "requires" : {
-            "Carp" : "0",
-            "Net::HTTP" : "0"
+            "Acme::HTTP" : "0.08",
+            "Carp" : "0"
          }
       }
    },
-   "provides" : {
-      "DebCnt" : {
-         "file" : "lib/XML/Reader/Testcases.pm"
-      },
-      "XML::Reader" : {
-         "file" : "lib/XML/Reader.pm",
-         "version" : "0.53"
-      },
-      "XML::Reader::Testcases" : {
-         "file" : "lib/XML/Reader/Testcases.pm",
-         "version" : "0.53"
-      },
-      "XML::Reader::Token" : {
-         "file" : "lib/XML/Reader.pm",
-         "version" : "0.53"
-      }
-   },
    "release_status" : "stable",
    "resources" : {
-      "license" : [
-         "http://dev.perl.org/licenses/"
-      ]
+      "repository" : {
+         "type" : "git",
+         "url" : "https://github.com/klaus03/XML-Reader.git",
+         "web" : "https://github.com/klaus03/XML-Reader"
+      }
    },
-   "version" : "0.53"
+   "version" : "0.64"
 }
@@ -1,32 +1,25 @@
 ---
-abstract: 'Reading XML and providing path information based on a pull-parser'
+abstract: 'Reading XML and providing path information based on a pull-parser.'
 author:
-  - unknown
-build_requires: {}
+  - 'Klaus Eichner <klaus03@gmail.com>'
+build_requires:
+  ExtUtils::MakeMaker: '0'
 configure_requires:
-  Module::Build: '0.3'
+  ExtUtils::MakeMaker: '0'
 dynamic_config: 1
-generated_by: 'Module::Build version 0.4205, CPAN::Meta::Converter version 2.141170'
+generated_by: 'ExtUtils::MakeMaker version 6.98, CPAN::Meta::Converter version 2.141170'
 license: perl
 meta-spec:
   url: http://module-build.sourceforge.net/META-spec-v1.4.html
   version: '1.4'
 name: XML-Reader
-provides:
-  DebCnt:
-    file: lib/XML/Reader/Testcases.pm
-  XML::Reader:
-    file: lib/XML/Reader.pm
-    version: '0.53'
-  XML::Reader::Testcases:
-    file: lib/XML/Reader/Testcases.pm
-    version: '0.53'
-  XML::Reader::Token:
-    file: lib/XML/Reader.pm
-    version: '0.53'
+no_index:
+  directory:
+    - t
+    - inc
 requires:
+  Acme::HTTP: '0.08'
   Carp: '0'
-  Net::HTTP: '0'
 resources:
-  license: http://dev.perl.org/licenses/
-version: '0.53'
+  repository: https://github.com/klaus03/XML-Reader.git
+version: '0.64'
@@ -6,8 +6,21 @@ use ExtUtils::MakeMaker;
 WriteMakefile(
     NAME              => 'XML::Reader',
     VERSION_FROM      => 'lib/XML/Reader.pm', # finds $VERSION
-    PREREQ_PM         => { 'Carp' => 0, 'Net::HTTP' => 0 }, # e.g., Module::Name => 1.1
+    PREREQ_PM         => { 'Carp' => 0, 'Acme::HTTP' => 0.08 }, # e.g., Module::Name => 1.1
     ($] >= 5.005 ?     ## Add these new keywords supported since 5.005
       (ABSTRACT_FROM  => 'lib/XML/Reader.pm', # retrieve abstract from module
        AUTHOR         => 'Klaus Eichner <klaus03@gmail.com>') : ()),
+	($ExtUtils::MakeMaker::VERSION >= 6.3002 ? ('LICENSE'=> 'perl') : ()),
+	(eval { ExtUtils::MakeMaker->VERSION(6.46) } ? (META_MERGE => {
+		'meta-spec' => { version => 2 },
+		resources => {
+			repository => {
+				type => 'git',
+				url  => 'https://github.com/klaus03/XML-Reader.git',
+				web  => 'https://github.com/klaus03/XML-Reader',
+			}
+		}})
+		: ()
+	),
+
 );
@@ -1,4 +1,4 @@
-XML-Reader Version 0.53
+XML-Reader Version 0.64
 
 Reading XML and providing path information based on a pull-parser.
 
@@ -9,7 +9,7 @@ our @ISA         = qw(Exporter);
 our %EXPORT_TAGS = ( all => [ qw(Get_TestCntr Get_TestProg) ] );
 our @EXPORT_OK   = ( @{ $EXPORT_TAGS{'all'} } );
 our @EXPORT      = qw();
-our $VERSION     = '0.53';
+our $VERSION     = '0.64';
 
 our %TestProg;
 
@@ -501,7 +501,7 @@ $TestProg{'0010_test_Module.t'} = [67, sub {
     }
 }];
 
-$TestProg{'0020_test_Module.t'} = [273, sub {
+$TestProg{'0020_test_Module.t'} = [281, sub {
     my ($XML_Reader_Any) = @_;
 
     Test::More::use_ok($XML_Reader_Any, qw(slurp_xml));
@@ -1038,6 +1038,7 @@ $TestProg{'0020_test_Module.t'} = [273, sub {
           { root => '/data/supplier',                branch => ['/']                          },
           { root => '/',                             branch => ['/data']                      },
           { root => '/',                             branch => ['/data/order']                },
+          { root => '/',                             branch => ['data/order']                 },
         );
 
         my @lines;
@@ -1058,7 +1059,11 @@ $TestProg{'0020_test_Module.t'} = [273, sub {
             push @lines, sprintf("Root: Ordr = %s", $_->[0]);
         }
 
-        Test::More::is(scalar(@lines),   9,                                                      'Pod-Test case no 19: number of output lines');
+        for (@{$aref->[4]}) {
+            push @lines, sprintf("Root: Ord2 = %s", $_->[0]);
+        }
+
+        Test::More::is(scalar(@lines),  10,                                                      'Pod-Test case no 19: number of output lines');
         Test::More::is($lines[ 0], "Cust: Name = smith   Street = high street  City = boston",   'Pod-Test case no 19: output line  0');
         Test::More::is($lines[ 1], "Cust: Name = jones   Street = maple street City = new york", 'Pod-Test case no 19: output line  1');
         Test::More::is($lines[ 2], "Cust: Name = stewart Street = ring road    City = dallas",   'Pod-Test case no 19: output line  2');
@@ -1068,6 +1073,177 @@ $TestProg{'0020_test_Module.t'} = [273, sub {
         Test::More::is($lines[ 6], "Supp: Name = jjj",                                           'Pod-Test case no 19: output line  6');
         Test::More::is($lines[ 7], "Root: Data = aabb",                                          'Pod-Test case no 19: output line  7');
         Test::More::is($lines[ 8], "Root: Ordr = ccdd",                                          'Pod-Test case no 19: output line  8');
+        Test::More::is($lines[ 9], "Root: Ord2 = ccdd",                                          'Pod-Test case no 19: output line  9');
+    }
+
+    {
+        my $line2 = q{
+        <data>
+          aa
+          <supplier>ggg</supplier>
+          <supplier>hhh</supplier>
+          <order no="A">
+            cc
+            <database loc='alpha'>
+              <item>
+                <customer name="smith" id="652">
+                  <street>high street</street>
+                  <city>boston</city>
+                </customer>
+                <customer name="jones" id="184">
+                  <street>maple street</street>
+                  <city>new york</city>
+                </customer>
+                <customer name="stewart" id="520">
+                  <street>ring road</street>
+                  <city>dallas</city>
+                </customer>
+              </item>
+              <item>
+                <customer name="smith" id="444">
+                  <street>upton way</street>
+                  <city>motown</city>
+                </customer>
+                <customer name="gates" id="959">
+                  <street>leave me thhis way</street>
+                  <city>cambridge</city>
+                </customer>
+                <customer name="stewart" id="914">
+                  <street>impossible way</street>
+                  <city>chicago</city>
+                </customer>
+              </item>
+            </database>
+            <database loc='beta'>
+              <item>
+                <customer name="smith" id="211">
+                  <street>place republique</street>
+                  <city>paris</city>
+                </customer>
+                <customer name="smith" id="123">
+                  <street>test drive</street>
+                  <city>Moscow</city>
+                </customer>
+                <customer name="stewart" id="999">
+                  <street>subway</street>
+                  <city>london</city>
+                </customer>
+              </item>
+            </database>
+          </order>
+          <dummy value="ttt">test</dummy>
+          <supplier>iii</supplier>
+          <supplier>jjj</supplier>
+          bb
+        </data>
+        };
+
+        my $aref = slurp_xml(\$line2,
+          { root => '/data/order/database[@loc="alpha"]/item', branch => [
+            'customer[@name="smith"]/street',
+            'customer[@name="stewart"]/street',
+          ] },
+        );
+
+        my @lines;
+
+        for (@{$aref->[0]}) {
+            push @lines, sprintf("Test2: smith = %-15s stewart = %s", $_->[0], $_->[1]);
+        }
+
+        Test::More::is(scalar(@lines),   2,                                                      'Pod-Test case no 19a: number of output lines');
+        Test::More::is($lines[ 0], "Test2: smith = high street     stewart = ring road",         'Pod-Test case no 19a: output line  0');
+        Test::More::is($lines[ 1], "Test2: smith = upton way       stewart = impossible way",    'Pod-Test case no 19a: output line  1');
+    }
+
+    {
+        my $line2 = q{
+          <data>
+            <database loc="alpha">
+              <item>
+                <customer name="smith" id="652">
+                  <street>high street</street>
+                  <city>rio</city>
+                </customer>
+                <customer name="jones" id="184">
+                  <street>maple street</street>
+                  <city>new york</city>
+                </customer>
+                <customer name="gates" id="520">
+                  <street>ring road</street>
+                  <city>dallas</city>
+                </customer>
+                <customer name="smith" id="800">
+                  <street>which way</street>
+                  <city>ny</city>
+                </customer>
+              </item>
+            </database>
+            <database loc="beta">
+              <item>
+                <customer name="smith" id="001">
+                  <street>nowhere</street>
+                  <city>st malo</city>
+                </customer>
+                <customer name="jones" id="002">
+                  <street>all the way</street>
+                  <city>leeds</city>
+                </customer>
+                <customer name="gates" id="003">
+                  <street>bypass</street>
+                  <city>rome</city>
+                </customer>
+              </item>
+            </database>
+            <database loc="alpha">
+              <item>
+                <customer name="peter" id="444">
+                  <street>upton way</street>
+                  <city>motown</city>
+                </customer>
+                <customer name="gates" id="959">
+                  <street>don't leave me this way</street>
+                  <city>cambridge</city>
+                </customer>
+              </item>
+            </database>
+            <database loc="alpha">
+              <item>
+                <customer name="smith" id="881">
+                  <street>anyway</street>
+                  <city>big apple</city>
+                </customer>
+                <customer name="thatcher" id="504">
+                  <street>baker street</street>
+                  <city>oxford</city>
+                </customer>
+              </item>
+            </database>
+          </data>
+        };
+
+        my @lines;
+
+        my $rdr = $XML_Reader_Any->new(\$line2, { mode => 'branches', sepchar => '|' }, {
+          root   => '/data/database[@loc="alpha"]',
+          branch => [
+            'item/customer[@name="smith"]/city',
+            'item/customer[@name="gates"]/city',
+        ]});
+
+        while ($rdr->iterate) {
+            my ($smith, $gates) = $rdr->value;
+
+            $smith = defined($smith) ? "($smith)" : 'undef';
+            $gates = defined($gates) ? "($gates)" : 'undef';
+
+            push @lines, sprintf("smith = %-12s, gates = %s", $smith, $gates);
+        }
+
+        Test::More::is(scalar(@lines),   3,                                                      'Pod-Test case no 19b: number of output lines');
+        Test::More::is($lines[ 0], "smith = (rio|ny)    , gates = (dallas)",                     'Pod-Test case no 19b: output line  0');
+        Test::More::is($lines[ 1], "smith = undef       , gates = (cambridge)",                  'Pod-Test case no 19b: output line  1');
+        Test::More::is($lines[ 2], "smith = (big apple) , gates = undef",                        'Pod-Test case no 19b: output line  2');
     }
 
     {
@@ -3,7 +3,11 @@ package XML::Reader;
 use strict;
 use warnings;
 use Carp;
-use Net::HTTP;
+
+use Acme::HTTP;
+
+set_timeout(10);
+set_redir_max(5);
 
 require Exporter;
 
@@ -11,7 +15,7 @@ our @ISA         = qw(Exporter);
 our %EXPORT_TAGS = ( all => [ qw(slurp_xml) ] );
 our @EXPORT_OK   = ( @{ $EXPORT_TAGS{'all'} } );
 our @EXPORT      = qw();
-our $VERSION     = '0.53';
+our $VERSION     = '0.64';
 
 my $use_module;
 
@@ -139,15 +143,9 @@ sub new {
         $fh = $_[0];
     }
     else {
-        if ($_[0] =~ m{\A http:}xms) {
-            my ($host, $get) = $_[0] =~ m{\A http:// ([^/]+) (/ .*) \z}xms ? ($1, $2) :
-              croak "Failed assertion #0041 in XML::Reader->new: Can't parse /http://.../.../ from '$_[0]'";
-
-            $fh = Net::HTTP->new(Host => $host)
-              or croak "Failed assertion #0042 in XML::Reader->new: Can't Net::HTTP->new(Host => '$host') because $@";
-
-            $fh->write_request(GET => $get, 'User-Agent' => 'Mozilla/5.0');
-            $fh->read_response_headers; # this function returns: $code, $msg, %h
+        if ($_[0] =~ m{\A https?:}xms) {
+            $fh = Acme::HTTP->new($_[0])
+              or croak "Failed assertion #0042 in XML::Reader->new: Can't Acme::HTTP->new('$_[0]') because $@";
         }
         else {
             open $fh, '<', $_[0] or croak "Failed assertion #0045 in XML::Reader->new: Can't open < '$_[0]' because $!";
@@ -235,28 +233,75 @@ sub new {
 
     if ($self->{filter} == 5) {
         for my $object (@_[2..$#_]) {
+            $object->{brna} = [];
+
+            if (ref($object->{branch}) eq 'ARRAY') {
+                for my $j (0..$#{$object->{branch}}) {
+                    $object->{branch}[$j] =~ s{\A ([^/\s])}{/$1}xms;
+
+                    $object->{brna}[$j] = [];
+
+                    my $b_level = 0;
+                    my $b_branch = $object->{branch}[$j];
+                    $object->{branch}[$j] =~ s{\[ [^/\]]* \]}''xmsg;
+
+                    $b_branch =~ s{\A /+}''xms;
+
+                    for my $ele (split(m{/}xms, $b_branch)) {
+                        $b_level++;
+
+                        if ($ele =~ m{\[ \@ ([^\[\]=\s]+) = ['"] ([^'"]*) ['"] \]}xms) {
+                            push @{$object->{brna}[$j]}, [ $b_level - 1, $1, $2 ];
+                        }
+                    }
+                }
+            }
+
+            $object->{rota} = [];
+
+            my $a_level = 0;
+            my $a_root = $object->{root};
+            $object->{root} =~ s{\[ [^/\]]* \]}''xmsg;
+            $a_root =~ s{\A /+}''xms;
+
+            for my $ele (split(m{/}xms, $a_root)) {
+                $a_level++;
+
+                if ($ele =~ m{\[ \@ ([^\[\]=\s]+) = ['"] ([^'"]*) ['"] \]}xms) {
+                    push @{$object->{rota}}, [ $a_level - 1, $1, $2 ];
+                }
+            }
+
             if ($object->{root} =~ m{\A // ([^/] .*) \z}xms
             or  $object->{root} =~ m{\A    ([^/] .*) \z}xms) {
                 my $chunk = $1;
                 push @{$self->{rlist}}, {
                     root   => undef,
-                    qr1    => qr{ / \Q$chunk\E \z}xms,
+                    qr1    => qr{\A (.*) / \Q$chunk\E \z}xms,
+                    rota   => $object->{rota},
                     qrfix  => undef,
                     branch => $object->{branch},
+                    brna   => $object->{brna},
                   };
             }
             else {
                 push @{$self->{rlist}}, {
                     root   => $object->{root},
+                    rota   => $object->{rota},
                     qr1    => undef,
                     qrfix  => undef,
                     branch => $object->{branch},
+                    brna   => $object->{brna},
                   };
             }
         }
+
+        #~ use Data::Dump;
+        #~ dd \@_;
     }
 
     $self->{plist}        = [];
+    $self->{alist}        = [];
     $self->{path}         = '/';
     $self->{prefix}       = '';
     $self->{tag}          = '';
@@ -343,11 +388,13 @@ sub iterate {
 
         if ($token->found_start_tag) {
             push @{$self->{plist}}, $token->extract_tag;
+            push @{$self->{alist}}, {};
             redo;
         }
 
         if ($token->found_end_tag) {
             pop @{$self->{plist}};
+            pop @{$self->{alist}};
             redo;
         }
 
@@ -388,6 +435,10 @@ sub iterate {
             $self->{type}         = 'T';
             $self->{att_hash}     = {@{$token->extract_attr}};
             $self->{dec_hash}     = {@{$token->extract_decl}};
+
+            for (keys %{$self->{att_hash}}) {
+                $self->{alist}[-1]{$_} = $self->{att_hash}{$_};
+            }
         }
         elsif ($token->found_attr) {
             my $key = $token->extract_attkey;
@@ -413,6 +464,8 @@ sub iterate {
             $self->{type}         = '@';
             $self->{att_hash}     = {};
             $self->{dec_hash}     = {};
+
+            $self->{alist}[-1]{$key} = $val;
         }
         else {
             croak "Failed assertion #0060 in subroutine XML::Reader->iterate: Found data type '".$token->[0]."'";
@@ -454,6 +507,8 @@ sub iterate {
                 my $border;
 
                 my $root;
+                my $rotn = 0;
+
                 if (defined $param->{root}) {
                     $root = $param->{root};
                 }
@@ -461,7 +516,8 @@ sub iterate {
                     $root = $param->{qrfix};
                 }
                 elsif (defined $param->{qr1}) {
-                    if ($self->{path} =~ $param->{qr1}) {
+                    if ($self->{path} =~ $param->{qr1}) { my $prf = $1;
+                        $rotn = () = $prf =~ m{/}xmsg;
                         $root = $self->{path};
                         $param->{qrfix} = $root;
                     }
@@ -492,6 +548,57 @@ sub iterate {
 
                 next unless defined $twig;
 
+                my $block = 0;
+
+                #~ if (@{$param->{rota}}) {
+                    #~ use Data::Dump;
+                    #~ print "\nDeb-0010: param->{rota}:\n";
+                    #~ dd $param->{rota};
+                    #~ print "\nDeb-0020: self->{alist}:\n";
+                    #~ dd $self->{alist};
+                #~ }
+
+                for (@{$param->{rota}}) {
+                    my ($offset, $attr, $val) = ($_->[0] + $rotn, $_->[1], $_->[2]);
+
+                    #~ print "Deb-0030: offset = $offset ($_->[0] + $rotn), attr = '$attr', val = '$val'\n";
+
+                    my $e = $self->{alist}[$offset];
+
+                    unless ($e) {
+                        #~ print "Deb-0100: Block-01\n";
+                        $block++;
+                        next;
+                    }
+
+                    my $v = $e->{$attr};
+
+                    unless (defined $v) {
+                        #~ print "Deb-0110: Block-02\n";
+                        $block++;
+                        next;
+                    }
+
+                    unless ($v eq $val) {
+                        #~ print "Deb-0120: Block-03\n";
+                        $block++;
+                        next;
+                    }
+
+                    #~ print "Deb-0150: Good...\n";
+                }
+
+                next if $block;
+
+                my $bran;
+
+                if ($root eq '/') {
+                    $bran = 0;
+                }
+                else {
+                    $bran = () = $root =~ m{/}xmsg;
+                }
+
                 if (ref $param->{branch}) { # here we have an array of branches...
                     if ($border and $self->{is_start}) {
                         $self->{bush}[$r] = [];
@@ -500,8 +607,51 @@ sub iterate {
                     if ($self->{is_value}) {
                         for my $i (0..$#{$param->{branch}}) {
                             if ($param->{branch}[$i] eq $twig) {
-                                my $ref = \$self->{bush}[$r][$i];
-                                $$ref .= (defined $$ref ? $self->{sepchar} : '').$self->{value};
+
+                                my $block = 0;
+
+                                #~ if (@{$param->{brna}[$i]}) {
+                                    #~ use Data::Dump;
+                                    #~ print "\nDeb-0010: param->{brna}[$i]:\n";
+                                    #~ dd $param->{brna}[$i];
+                                    #~ print "\nDeb-0020: self->{alist}:\n";
+                                    #~ dd $self->{alist};
+                                #~ }
+
+                                for (@{$param->{brna}[$i]}) {
+                                    my ($offset, $attr, $val) = ($_->[0] + $bran, $_->[1], $_->[2]);
+
+                                    #~ print "Deb-0030: offset = $offset ($_->[0] + $bran), attr = '$attr', val = '$val'\n";
+
+                                    my $e = $self->{alist}[$offset];
+
+                                    unless ($e) {
+                                        #~ print "Deb-0100: Block-01\n";
+                                        $block++;
+                                        next;
+                                    }
+
+                                    my $v = $e->{$attr};
+
+                                    unless (defined $v) {
+                                        #~ print "Deb-0110: Block-02\n";
+                                        $block++;
+                                        next;
+                                    }
+
+                                    unless ($v eq $val) {
+                                        #~ print "Deb-0120: Block-03\n";
+                                        $block++;
+                                        next;
+                                    }
+
+                                    #~ print "Deb-0150: Good...\n";
+                                }
+
+                                unless ($block) {
+                                    my $ref = \$self->{bush}[$r][$i];
+                                    $$ref .= (defined $$ref ? $self->{sepchar} : '').$self->{value};
+                                }
                             }
                         }
                     }
@@ -617,12 +767,11 @@ sub get_token {
     my $self = shift;
 
     until (@{$self->NB_data}) {
-
         # Here is the all important reading of a chunk of XML-data from the filehandle...
 
         my $buf;
 
-        if (ref($self->NB_fh) eq 'Net::HTTP') {
+        if (ref($self->NB_fh) eq 'Acme::HTTP') {
             my $ct = $self->NB_fh->read_entity_body($buf, 4096); # returns number of bytes read, or undef if IO-Error
             last unless $ct;
         }
@@ -851,7 +1000,7 @@ sub slurp_xml {
 
 package XML::Reader::Token;
 
-our $VERSION = '0.53';
+our $VERSION = '0.64';
 
 sub found_start_tag   { $_[0][0] eq '<'; }
 sub found_end_tag     { $_[0][0] eq '>'; }
@@ -1879,8 +2028,8 @@ that {branch => '+'} means that the data is returned as an array of PYX elements
 In the following program we will use function rdr->rvalue to obtain the data:
 
   my $rdr = XML::Reader->new(\$line2, {filter => 5},
-    { root => 'customer',       branch => ['/@name', '/street', '/city'] },
-    { root => '/data/supplier', branch => ['/']                          },
+    { root => 'customer',       branch => ['@name', 'street', 'city'] },
+    { root => '/data/supplier', branch => ['/']                       },
     { root => '//customer',     branch => '*' },
     { root => 'p',              branch => '*' },
     { root => '//customer',     branch => '+' },
@@ -1980,7 +2129,7 @@ This is the output:
 We can also use function rdr->value to obtain the same data:
 
   my $rdr = XML::Reader->new(\$line2, {filter => 5},
-    { root => 'customer',       branch => ['/@name', '/street', '/city'] },
+    { root => 'customer',       branch => ['@name', 'street', 'city'] },
     { root => 'p',              branch => '*' },
   );
 
@@ -2167,6 +2316,100 @@ You could combine {mode => 'branches'} and regular expressions to parse the XML:
       }
   }
 
+=head2 Example Attribut conditions
+
+Let's also consider a different example ($text3):
+
+  my $text3 = q{
+    <data>
+      <database loc="alpha">
+        <item>
+          <customer name="smith" id="652">
+            <street>high street</street>
+            <city>rio</city>
+          </customer>
+          <customer name="jones" id="184">
+            <street>maple street</street>
+            <city>new york</city>
+          </customer>
+          <customer name="gates" id="520">
+            <street>ring road</street>
+            <city>dallas</city>
+          </customer>
+          <customer name="smith" id="800">
+            <street>which way</street>
+            <city>ny</city>
+          </customer>
+        </item>
+      </database>
+      <database loc="beta">
+        <item>
+          <customer name="smith" id="001">
+            <street>nowhere</street>
+            <city>st malo</city>
+          </customer>
+          <customer name="jones" id="002">
+            <street>all the way</street>
+            <city>leeds</city>
+          </customer>
+          <customer name="gates" id="003">
+            <street>bypass</street>
+            <city>rome</city>
+          </customer>
+        </item>
+      </database>
+      <database loc="alpha">
+        <item>
+          <customer name="peter" id="444">
+            <street>upton way</street>
+            <city>motown</city>
+          </customer>
+          <customer name="gates" id="959">
+            <street>don't leave me this way</street>
+            <city>cambridge</city>
+          </customer>
+        </item>
+      </database>
+      <database loc="alpha">
+        <item>
+          <customer name="smith" id="881">
+            <street>anyway</street>
+            <city>big apple</city>
+          </customer>
+          <customer name="thatcher" id="504">
+            <street>baker street</street>
+            <city>oxford</city>
+          </customer>
+        </item>
+      </database>
+    </data>
+  };
+
+You can also use attribute conditions ('/path1[@attr="val"]/...') inside the path statements
+(root => ... and branch => ...) like so:
+
+  my $rdr = XML::Reader->new(\$text3, {mode => 'branches', sepchar => '|'}, {
+    root   => '/data/database[@loc="alpha"]',
+    branch => [
+      'item/customer[@name="smith"]/city',
+      'item/customer[@name="gates"]/city',
+    ]});
+
+  while ($rdr->iterate) {
+      my ($smith, $gates) = $rdr->value;
+
+      $smith = defined($smith) ? "'$smith'" : 'undef';
+      $gates = defined($gates) ? "'$gates'" : 'undef';
+
+      printf "smith = %-12s, gates = %s\n", $smith, $gates;
+  }
+
+The output is as follows:
+
+  smith = 'rio|ny'    , gates = 'dallas'
+  smith = undef       , gates = 'cambridge'
+  smith = 'big apple' , gates = undef
+
 =head1 FUNCTIONS
 
 =head2 Function slurp_xml
@@ -2205,8 +2448,8 @@ the path '/data/order/database/customer' and we also want to slurp the supplier
   };
 
   my $aref = slurp_xml(\$line2,
-    { root => '/data/order/database/customer', branch => ['/@name', '/street', '/city'] },
-    { root => '/data/supplier',                branch => '*'                            },
+    { root => '/data/order/database/customer', branch => ['@name', 'street', 'city'] },
+    { root => '/data/supplier',                branch => '*'                         },
   );
 
   for (@{$aref->[0]}) {
@@ -2223,7 +2466,7 @@ The first parameter to slurp_xml is the filename (or scalar reference, or open f
 that will be slurped. In this case we read from a scalar ref \$line2. The next parameter is a hash-ref
 with the root of the sub-tree that we want to slurp (in our case that's '/data/order/database/customer')
 and the branches, a list of the elements that we want to slurp, relative to the sub-tree. In this
-case it is ['/@name', '/street', '/city']. The next parameter is our second root/branch definition, in
+case it is ['@name', 'street', 'city']. The next parameter is our second root/branch definition, in
 this case it is root => '/data/supplier' with branch => ['/'].
 
 Here is the output:
@@ -1033,8 +1033,8 @@ hat dass eine Liste von PYX Instruktionen zurE<uuml>ckgegeben wird.
 Im folgenden Programm benutzen wir die Funktion $rdr->rvalue um die Daten zu erhalten:
 
   my $rdr = XML::Reader->new(\$line2, {filter => 5},
-    { root => 'customer',       branch => ['/@name', '/street', '/city'] },
-    { root => '/data/supplier', branch => ['/']                          },
+    { root => 'customer',       branch => ['@name', 'street', 'city'] },
+    { root => '/data/supplier', branch => ['/']                       },
     { root => '//customer',     branch => '*' },
     { root => 'p',              branch => '*' },
     { root => '//customer',     branch => '+' },
@@ -1134,7 +1134,7 @@ Hier ist das Ergebnis:
 Wir kE<ouml>nnen ebenso die Funktion $rdr->value benutzen um die gleichen Daten zu erhalten:
 
   my $rdr = XML::Reader->new(\$line2, {filter => 5},
-    { root => 'customer',       branch => ['/@name', '/street', '/city'] },
+    { root => 'customer',       branch => ['@name', 'street', 'city'] },
     { root => 'p',              branch => '*' },
   );
 
@@ -1322,6 +1322,99 @@ Sie kE<ouml>nnen {filter => 5, mode => 'branches'} und regulE<auml>re AusdrE<uum
       }
   }
 
+=head2 Beispiel Attribut Bedingungen
+
+Wir betrachten nun ein weiteres Beispiel ($text3):
+
+  my $text3 = q{
+    <data>
+      <database loc="alpha">
+        <item>
+          <customer name="smith" id="652">
+            <street>high street</street>
+            <city>rio</city>
+          </customer>
+          <customer name="jones" id="184">
+            <street>maple street</street>
+            <city>new york</city>
+          </customer>
+          <customer name="gates" id="520">
+            <street>ring road</street>
+            <city>dallas</city>
+          </customer>
+          <customer name="smith" id="800">
+            <street>which way</street>
+            <city>ny</city>
+          </customer>
+        </item>
+      </database>
+      <database loc="beta">
+        <item>
+          <customer name="smith" id="001">
+            <street>nowhere</street>
+            <city>st malo</city>
+          </customer>
+          <customer name="jones" id="002">
+            <street>all the way</street>
+            <city>leeds</city>
+          </customer>
+          <customer name="gates" id="003">
+            <street>bypass</street>
+            <city>rome</city>
+          </customer>
+        </item>
+      </database>
+      <database loc="alpha">
+        <item>
+          <customer name="peter" id="444">
+            <street>upton way</street>
+            <city>motown</city>
+          </customer>
+          <customer name="gates" id="959">
+            <street>don't leave me this way</street>
+            <city>cambridge</city>
+          </customer>
+        </item>
+      </database>
+      <database loc="alpha">
+        <item>
+          <customer name="smith" id="881">
+            <street>anyway</street>
+            <city>big apple</city>
+          </customer>
+          <customer name="thatcher" id="504">
+            <street>baker street</street>
+            <city>oxford</city>
+          </customer>
+        </item>
+      </database>
+    </data>
+  };
+
+Jetzt kann man in den Pfaden (root => ... and branch => ...) Attribut Bedingungen
+hinzufE<uuml>gen ('/path1[@attr="val"]/...'), z.B.:
+
+  my $rdr = XML::Reader->new(\$text3, {mode => 'branches', sepchar => '|'}, {
+    root   => '/data/database[@loc="alpha"]',
+    branch => [
+      'item/customer[@name="smith"]/city',
+      'item/customer[@name="gates"]/city',
+    ]});
+
+  while ($rdr->iterate) {
+      my ($smith, $gates) = $rdr->value;
+
+      $smith = defined($smith) ? "'$smith'" : 'undef';
+      $gates = defined($gates) ? "'$gates'" : 'undef';
+
+      printf "smith = %-12s, gates = %s\n", $smith, $gates;
+  }
+
+Das Ergebnis sieht wie folgt aus:
+
+  smith = 'rio|ny'    , gates = 'dallas'
+  smith = undef       , gates = 'cambridge'
+  smith = 'big apple' , gates = undef
 
 =head1 FUNKTIONEN
 
@@ -1361,8 +1454,8 @@ ein Beispiel in dem wir den Namen, die Strasse und die Stadt fE<uuml>r alle Kund
   };
 
   my $aref = slurp_xml(\$line2,
-    { root => '/data/order/database/customer', branch => ['/@name', '/street', '/city'] },
-    { root => '/data/supplier',                branch => '*'                            },
+    { root => '/data/order/database/customer', branch => ['@name', 'street', 'city'] },
+    { root => '/data/supplier',                branch => '*'                         },
   );
 
   for (@{$aref->[0]}) {
@@ -1379,7 +1472,7 @@ Der erste Parameter in slurp_xml ist entweder der Dateiname (oder eine Skalar Re
 Dateihandle) der XML Datei die wir einlesen wollen. In diesem Fall lesen wir von der Skalar Referenz \$line2.
 Der nE<auml>chste Parameter ist die Wurzel des Baumes den wir einlesen wollen (in diesem Falle wE<auml>re das
 '/data/order/database/customer') mit einer Liste von Elementen die wir, relativ zur Wurzel, selektieren
-wollen, in diesem Falle wE<auml>re das ['/@name', '/street', '/city']. Der darauffolgende Parameter ist eine
+wollen, in diesem Falle wE<auml>re das ['@name', 'street', 'city']. Der darauffolgende Parameter ist eine
 zweite Wurzel (root/branch Definition), in diesem Falle ist es root => '/data/supplier' mit branch => ['/'].
 
 Hier ist das Resultat:
@@ -46,7 +46,7 @@ que l'appel a rE<eacute>ussi:
 Normalement, on n'utilise pas XML::Reader tout seul, on utilise plutE<ocirc>t XML::Reader::RS (qui utilise XML::Parser) ou
 on utilise XML::Reader::PP (qui utilise XML::Parsepp).
 
-Par contre, si on veut utiliser XML::Reader directement, voici la procédure pour choisir entre XML::Parser et XML::Parsepp:
+Par contre, si on veut utiliser XML::Reader directement, voici la procE<eacute>dure pour choisir entre XML::Parser et XML::Parsepp:
 
 XML::Reader utilise XML::Parser comme sous-module. Cette configuration marche trE<egrave>s bien, sauf dans le cas oE<ugrave>
 il n'y a pas de compilateur C disponible pour installer XML::Parser. Dans ce cas, XML::Parsepp peut remplacer XML::Parser.
@@ -1021,8 +1021,8 @@ le paramE<egrave>tre {branch => '+'} indique que le rE<eacute>sultat sera une li
 Dans le programme ci-dessus on va utiliser la fonction $rdr->rvalue pour lire les donnees:
 
   my $rdr = XML::Reader->new(\$line2, {filter => 5},
-    { root => 'customer',       branch => ['/@name', '/street', '/city'] },
-    { root => '/data/supplier', branch => ['/']                          },
+    { root => 'customer',       branch => ['@name', 'street', 'city'] },
+    { root => '/data/supplier', branch => ['/']                       },
     { root => '//customer',     branch => '*' },
     { root => 'p',              branch => '*' },
     { root => '//customer',     branch => '+' },
@@ -1122,7 +1122,7 @@ Voici le rE<eacute>sultat:
 Nous pouvons E<eacute>galement utiliser la fonction $rdr->value pour obtenir les mE<ecirc>mes donnE<eacute>es:
 
   my $rdr = XML::Reader->new(\$line2, {filter => 5},
-    { root => 'customer',       branch => ['/@name', '/street', '/city'] },
+    { root => 'customer',       branch => ['@name', 'street', 'city'] },
     { root => 'p',              branch => '*' },
   );
 
@@ -1311,6 +1311,100 @@ On peut combiner {filter => 5, mode => 'branches'} avec des expressions rE<eacut
       }
   }
 
+=head2 Exemple condition d'attribut
+
+Ci-dessous un autre document XML ($text3):
+
+  my $text3 = q{
+    <data>
+      <database loc="alpha">
+        <item>
+          <customer name="smith" id="652">
+            <street>high street</street>
+            <city>rio</city>
+          </customer>
+          <customer name="jones" id="184">
+            <street>maple street</street>
+            <city>new york</city>
+          </customer>
+          <customer name="gates" id="520">
+            <street>ring road</street>
+            <city>dallas</city>
+          </customer>
+          <customer name="smith" id="800">
+            <street>which way</street>
+            <city>ny</city>
+          </customer>
+        </item>
+      </database>
+      <database loc="beta">
+        <item>
+          <customer name="smith" id="001">
+            <street>nowhere</street>
+            <city>st malo</city>
+          </customer>
+          <customer name="jones" id="002">
+            <street>all the way</street>
+            <city>leeds</city>
+          </customer>
+          <customer name="gates" id="003">
+            <street>bypass</street>
+            <city>rome</city>
+          </customer>
+        </item>
+      </database>
+      <database loc="alpha">
+        <item>
+          <customer name="peter" id="444">
+            <street>upton way</street>
+            <city>motown</city>
+          </customer>
+          <customer name="gates" id="959">
+            <street>don't leave me this way</street>
+            <city>cambridge</city>
+          </customer>
+        </item>
+      </database>
+      <database loc="alpha">
+        <item>
+          <customer name="smith" id="881">
+            <street>anyway</street>
+            <city>big apple</city>
+          </customer>
+          <customer name="thatcher" id="504">
+            <street>baker street</street>
+            <city>oxford</city>
+          </customer>
+        </item>
+      </database>
+    </data>
+  };
+
+En utilisant des chemins (root => ... and branch => ...) on peut rajouter des conditions d'attribut
+('/path1[@attr="val"]/...'), par ex.:
+
+  my $rdr = XML::Reader->new(\$text3, {mode => 'branches', sepchar => '|'}, {
+    root   => '/data/database[@loc="alpha"]',
+    branch => [
+      'item/customer[@name="smith"]/city',
+      'item/customer[@name="gates"]/city',
+    ]});
+
+  while ($rdr->iterate) {
+      my ($smith, $gates) = $rdr->value;
+
+      $smith = defined($smith) ? "'$smith'" : 'undef';
+      $gates = defined($gates) ? "'$gates'" : 'undef';
+
+      printf "smith = %-12s, gates = %s\n", $smith, $gates;
+  }
+
+Voici le rE<eacute>sultat:
+
+  smith = 'rio|ny'    , gates = 'dallas'
+  smith = undef       , gates = 'cambridge'
+  smith = 'big apple' , gates = undef
+
 =head1 FONCTIONS
 
 =head2 Fonction slurp_xml
@@ -1349,8 +1443,8 @@ le chemin '/data/order/database/customer'. Nous souhaitons aussi d'aspirer le 's
   };
 
   my $aref = slurp_xml(\$line2,
-    { root => '/data/order/database/customer', branch => ['/@name', '/street', '/city'] },
-    { root => '/data/supplier',                branch => '*'                            },
+    { root => '/data/order/database/customer', branch => ['@name', 'street', 'city'] },
+    { root => '/data/supplier',                branch => '*'                         },
   );
 
   for (@{$aref->[0]}) {
@@ -1368,7 +1462,7 @@ un scalaire, ou une rE<eacute>fE<eacute>rence E<agrave> un fichier ouvert) du XM
 Dans notre cas nous avons une rE<eacute>fE<eacute>rence E<agrave> un scalaire \$line2. Le paramE<egrave>tre suivant
 est la racine de l'arbre qu'on veut aspirer (dans notre cas c'est '/data/order/database/customer') et
 nous donnons une liste des E<eacute>lE<eacute>ments que nous souhaitons sE<eacute>lectionner, relative
-E<agrave> la racine. Dans notre cas c'est ['/@name', '/street', '/city']. Le paramE<egrave>tre suivant est
+E<agrave> la racine. Dans notre cas c'est ['@name', 'street', 'city']. Le paramE<egrave>tre suivant est
 la deuxiE<egrave>me racine (dE<eacute>finition root/branch), dans ce cas c'est root => '/data/supplier' avec
 branch => ['/'].