@@ -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 <
- + > into >
- + & into &
- + ' into '
- + " into "
- - 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 <
+ char > into >
+ char & into &
+ char ' into '
+ char " into "
+
+
+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 => ['/'].