=head1 NAME

XML::Compile::Schema::XmlReader - bricks to translate XML to HASH

=head1 INHERITANCE

=head1 SYNOPSIS

 my $schema = XML::Compile::Schema->new(...);
 my $code   = $schema->compile(READER => ...);

=head1 DESCRIPTION

The translator understands schemas, but does not encode that into
actions.  This module implements those actions to translate from XML
into a (nested) Perl HASH structure.

=head1 DETAILS

=head2 Processing Wildcards

If you want to collect information from the XML structure, which is
permitted by C<any> and C<anyAttribute> specifications in the schema,
you have to implement that yourself.  The problem is C<XML::Compile>
has less knowledge than you about the possible data.

=head3 anyAttribute

By default, the C<anyAttribute> specification is ignored.  When C<TAKE_ALL>
is given, all attributes which are fulfilling the name-space requirement
added to the returned data-structure.  As key, the absolute element name
will be used, with as value the related unparsed XML element.

In the current implementation, if an explicit attribute is also
covered by the name-spaces permitted by the anyAttribute definition,
then it will also appear in that list (and hence the handler will
be called as well).

Use L<XML::Compile::Schema::compile(anyAttribute)|XML::Compile::Schema/"Compilers"> to write your
own handler, to influence the behavior.  The handler will be called for
each attribute, and you must return list of pairs of derived information.
When the returned is empty, the attribute data is lost.  The value may
be a complex structure.

example: anyAttribute in XmlReader

Say your schema looks like this:

 <schema targetNamespace="http://mine"
    xmlns:me="http://mine" ...>
   <element name="el">
     <complexType>
       <attribute name="a" type="xs:int" />
       <anyAttribute namespace="##targetNamespace"
          processContents="lax">
     </complexType>
   </element>
   <simpleType name="non-empty">
     <restriction base="NCName" />
   </simpleType>
 </schema>

Then, in an application, you write:

 my $r = $schema->compile
  ( READER => pack_type('http://mine', 'el')
  , anyAttribute => 'ALL'
  );
 # or lazy: READER => '{http://mine}el'

 my $h = $r->( <<'__XML' );
   <el xmlns:me="http://mine">
     <a>42</a>
     <b type="me:non-empty">
        everything
     </b>
   </el>
 __XML

 use Data::Dumper 'Dumper';
 print Dumper $h;
 __XML__

The output is something like

 $VAR1 =
  { a => 42
  , '{http://mine}a' => ... # XML::LibXML::Node with <a>42</a>
  , '{http://mine}b' => ... # XML::LibXML::Node with <b>everything</b>
  };

You can improve the reader with a callback.  When you know that the
extra attribute is always of type C<non-empty>, then you can do

 my $read = $schema->compile
  ( READER => '{http://mine}el'
  , anyAttribute => \&filter
  );

 my $anyAttRead = $schema->compile
  ( READER => '{http://mine}non-empty'
  );

 sub filter($$$$)
 {   my ($fqn, $xml, $path, $translator) = @_;
     return () if $fqn ne '{http://mine}b';
     (b => $anyAttRead->($xml));
 }

 my $h = $r->( see above );
 print Dumper $h;

Which will result in

 $VAR1 =
  { a => 42
  , b => 'everything'
  };

The filter will be called twice, but return nothing in the first
case.  You can implement any kind of complex processing in the filter.

=head3 any element

By default, the C<any> definition in a schema will ignore all elements
from the container which are not used.  Also in this case C<TAKE_ALL>
is required to produce C<any> results.  C<SKIP_ALL> will ignore all
results, although this are being processed for validation needs.

The C<minOccurs> and C<maxOccurs> of C<any> are ignored: the amount of
elements is always unbounded.  Therefore, you will get an array of
elements back per type. 

=head2 Schema hooks

=head3 hooks executed before the XML is being processed

The C<before> hooks receives an XML::LibXML::Node object and
the path string.  It must return a new (or same) XML node which
will be used from then on.  You probably can best modify a node
clone, not the original as provided by the user.  When C<undef>
is returned, the whole node will disappear.

This hook offers a predefined C<PRINT_PATH>.

example: to trace the paths

 $schema->addHook(path => qr/./, before => 'PRINT_PATH');

=head3 hooks executed as replacement

Your C<replace> hook should return a list of key-value pairs. To
produce it, it will get the XML::LibXML::Node, the translator settings
as HASH, the path, and the localname.

This hook has a predefined C<SKIP>, which will not process the
found element, but simply return the string C<SKIPPED> as value.
This way, a whole tree of unneeded translations can be avoided.

=head3 hooks for post-processing, after the data is collected

The data is collect, and passed as second argument after the XML
node.  The third argument is the path.  Be careful that the
collected data might be a SCALAR (for simpleType).

This hook also offers a predefined C<PRINT_PATH>.  Besides, it
has C<XML_NODE>, C<ELEMENT_ORDER>, and C<ATTRIBUTE_ORDER>, which will
result in additional fields in the HASH, respectively containing the
CODE which was processed, the element names and the attribute names.
The keys start with an underscore C<_>.

=head1 SEE ALSO

This module is part of XML-Compile distribution version 0.66,
built on January 31, 2008. Website: F<http://perl.overmeer.net/xml-compile/>

=head1 LICENSE

Copyrights 2006-2008 by Mark Overmeer. For other contributors see ChangeLog.

This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.
See F<http://www.perl.com/perl/misc/Artistic.html>

