NAME¶
XML::Compile::Translate::Writer - translate HASH to XML
INHERITANCE¶
XML::Compile::Translate::Writer
is a XML::Compile::Translate
SYNOPSIS¶
my $schema = XML::Compile::Schema->new(...);
my $code = $schema->compile(WRITER => ...);
DESCRIPTION¶
The translator understands schemas, but does not encode that into actions. This
module implements those actions to translate from a (nested) Perl HASH
structure onto XML.
Extends "DESCRIPTION" in XML::Compile::Translate.
METHODS¶
Extends "METHODS" in XML::Compile::Translate.
DETAILS¶
Extends "DETAILS" in XML::Compile::Translate.
Translator options¶
Extends "Translator options" in XML::Compile::Translate.
Processing Wildcards¶
Complex elements can define "any" (element) and
"anyAttribute" components, with unpredictable content. In this case,
you are quite on your own in processing those constructs. The use of both
schema components should be avoided: please specify your data-structures
explicit by clean type extensions.
The procedure for the WRITER is simple: add key-value pairs to your hash, in
which the value is a fully prepared XML::LibXML::Attr or XML::LibXML::Element.
The keys have the form "{namespace}type". The
namespace
component is important, because only spec conformant namespaces will be used.
The elements and attributes are added in random order.
Mixed elements¶
[0.79] ComplexType and ComplexContent components can be declared with the
"<mixed="true""> attribute.
XML::Compile does not have a way to express these mixtures of information and
text as Perl data-structures; the only way you can use those to the full
extend, is by juggling with XML::LibXML nodes yourself.
You may provide a XML::LibXML::Element, which is complete, or a HASH which
contains attributes values and an XML node with key '_'. When '_' contains a
string, it will be translated into an XML text node.
XML::Compile::Schema::compile(mixed_elements) can be set to
- ATTRIBUTES (default)
- Add attributes to the provided node.
- STRUCTURAL
- [0.89] behaves as if the attribute is not there: a data-structure can be
used or an XML node.
Schema hooks¶
All writer hooks behave differently. Be warned that the user values can be a
SCALAR or a HASH, dependent on the type. You can intervene on higher
data-structure levels, to repair lower levels, if you want to.
hooks executed before normal processing
The "before" hook gives you the opportunity to fix the user supplied
data structure. The XML generator will complain about missing, superfluous,
and erroneous values which you probably want to avoid.
The "before" hook returns new values. Just must not interfere with the
user provided data. When "undef" is returned, the whole node will be
cancelled.
On the moment, the only predefined "before" hook is
"PRINT_PATH".
hooks replacing the usual XML node generation
Only one "replace" hook can be defined. It must return a
XML::LibXML::Node or "undef". The hook must use the
"XML::LibXML::Document" node (which is provided as first argument)
to create a node.
As parameters, the called replace function will receive the document,
user-provided values, location in the data tree (for error messages), the tag
of the node with prefix attached, and a reference to the code which would be
executed if the replace hook had not been active.
On the moment, the only predefined "replace" hook is "SKIP".
hooks executed after the node was created
The "after" hooks, will each get a chance to modify the produced XML
node, for instance to encapsulate it. Each time, the new XML node has to be
returned.
On the moment, the only predefined "after" hook is
"PRINT_PATH".
fixing bad schemas
When a schema makes a mess out of things, we can fix that with hooks. Also, when
you need things that XML::Compile does not support (yet).
Typemaps¶
In a typemap, a relation between an XML element type and a Perl class (or
object) is made. Each translator back-end will implement this a little
differently. This section is about how the writer handles typemaps.
Typemap to Class
Usually, an XML type will be mapped on a Perl class. The Perl class implements
the "toXML" method as serializer. That method should either return a
data structure which fits that of the specific type, or an
XML::LibXML::Element.
When translating the data-structure to XML, the process may encounter objects.
Only if these objects appear at locations where a typemap is defined, they are
treated smartly. When some other data than an objects is found on a location
which has a typemap definition, it will be used as such; objects are optional.
The object (of present) will be checked to be of the expected class. It will be
a compile-time error when the class does not implement the
"toXML"method.
$schema->typemap($sometype => 'My::Perl::Class');
package My::Perl::Class;
...
sub toXML
{ my ($self, $xmltype, $doc) = @_;
...
{ a => { b => 42 }, c => 'aaa' };
}
The $self is the object found in the data-structure provided by the user. $doc
can be used to create your own XML::LibXML::Element. It is possible to use the
same object on locations for different types: in this case, the toXML method
can distiguisk what kind of data to return based on the $xmltype.
Typemap to Object
In this case, some helper object arranges the serialization of the provided
object. This is especially useful when the provided object does not have the
toXML implemented, for instance because it is an implementation not under your
control. The helper object works like an interface.
my $object = My::Perl::Class->new(...);
$schema->typemap($sometype => $object);
package My::Perl::Class;
sub toXML
{ my ($self, $object, $xmltype, $doc) = @_;
...
}
The toXML will only be called then $object is blessed. If you wish to have
access to some data-type in any case, then use a simple "before"
hook.
Typemap to CODE
The light version of an interface object uses CODE references. The CODE
reference is only called if a blessed value is found in the user provided
data. It cannot be checked automatically whether it is blessed according to
the expectation.
$schema->typemap($t1 => \&myhandler);
sub myhandler
{ my ($backend, $object, $xmltype, $doc) = @_;
...
}
Typemap implementation
The typemap for the writer is implemented as a 'before' hook: just before the
writer wants to start.
Of course, it could have been implemented by accepting an object anywhere in the
input data. However, this would mean that all the (many) internal parser
constructs would need to be extended. That would slow-down the writer
considerably.
SEE ALSO¶
This module is part of XML-Compile distribution version 1.47, built on October
11, 2014. Website:
http://perl.overmeer.net/xml-compile/
Other distributions in this suite: XML::Compile, XML::Compile::SOAP,
XML::Compile::WSDL11, XML::Compile::SOAP12, XML::Compile::SOAP::Daemon,
XML::Compile::SOAP::WSA, XML::Compile::C14N, XML::Compile::WSS,
XML::Compile::WSS::Signature, XML::Compile::Tester, XML::Compile::Cache,
XML::Compile::Dumper, XML::Compile::RPC, XML::Rewrite and XML::LibXML::Simple.
Please post questions or ideas to the mailinglist at
http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/xml-compile . For
live contact with other developers, visit the "#xml-compile" channel
on "irc.perl.org".
LICENSE¶
Copyrights 2006-2014 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
http://www.perl.com/perl/misc/Artistic.html