2008-08-13 MARKOV Solutions Mark Overmeer MARKOV@cpan.org YAPC::EU 2008 From XML (schema) to...

Post on 01-Jan-2016

219 views 3 download

transcript

2008-08-13

MARKOV Solutionshttp://perl.overmeer.net

Mark OvermeerMARKOV@cpan.org

YAPC::EU 2008

From XML (schema) to Application

2008-08-13

MARKOV Solutionshttp://perl.overmeer.net

Mark OvermeerMARKOV@cpan.org

YAPC::EU 2008

From XML (schema) to Application

I HATE XML

3

Objective

XML schema's are very popular

Schema/XML complicationsname-spacesstrongly typedverbose notationoften generated

Application complicationsmessage validation: strictnessschema locationschema versioning

XML::Compile suite helps!

4

XML::Compile

Advantages over other XML modules:very strict following the rules: no DWIM, no guessingusually no need for name-space understanding"slow" compile phase, then fast runvery close to 100% support: no known bugs

5

XML::Compile

Advantages over other XML modules:very strict following the rules: no DWIM, no guessingusually no need for name-space understanding"slow" compile phase, then fast runvery close to 100% support: no known bugs

my $schema = XML::Compile::Schema->new($xsdfile);

6

XML::Compile

Advantages over other XML modules:very strict following the rules: no DWIM, no guessingusually no need for name-space understanding"slow" compile phase, then fast runvery close to 100% support: no known bugs

my $schema = XML::Compile::Schema->new($xsdfile);

my $read = $schema->compile(READER => '{myns}mytype');my $hash = $read->($xml);print Dumper $hash;

7

XML::Compile

Advantages over other XML modules:very strict following the rules: no DWIM, no guessingusually no need for name-space understanding"slow" compile phase, then fast runvery close to 100% support: no known bugs

my $schema = XML::Compile::Schema->new($xsdfile);

my $read = $schema->compile(READER => '{myns}mytype');my $hash = $read->($xml);print Dumper $hash;

my $doc = XML::LibXML::Document->new('1.0', 'UTF-8');my $write = $schema->compile(WRITER => '{myns}mytype');my $xml = $write->($doc, $hash);print $xml->toString(1);

8

XML::Compile::Schema

Collects information from all used schema's

Organizes compilationX::C::Translate, with back-ends

X::C::T::Reader XML → HASHX::C::T::Writer HASH → XMLX::C::T::Template example generator

built-in typesname-space administration

Compilation results in code-refs

9

XML::Compile::Cache

Extends X::C::Schemacompiled code-ref managementcompile option managementpre-compile for daemons orcompile-on-demand single shotuse of prefixes

10

XML::Compile::Cache

Extends X::C::Schemacompiled code-ref managementcompile option managementpre-compile for daemons orcompile-on-demand single shotuse of prefixes

my @p = (myprefix => $mynamespace);my $schema = XML::Compile::Cache->new(prefixes => \@p);my $type = 'myprefix:mylocal'; # {mynamespace}mylocal

$schema->declare(READER => $type, @options);

# $schema->compileAll

my $data = $schema->reader($type)->($xml);my $xml = $schema->writer($type)->($doc, $data);

11

Other modules for XML::Compile

XML::Compile::SOAP11XML::Compile::WSDL11

my $wsdl = XML::Compile::WSDL11->new($wsdlfile);my $call = $wsdl->compileClient('CallName');

my ($answer, $trace) = $call->($request);

12

Other modules for XML::Compile

XML::Compile::SOAP11XML::Compile::WSDL11

XML::Compile::SOAP::Daemon

based on Net::Server and HTTP::Daemon

my $wsdl = XML::Compile::WSDL11->new($wsdlfile);my $call = $wsdl->compileClient('CallName');

my ($answer, $trace) = $call->($request);

my $daemon = XML::Compile::SOAP::HTTPDaemon->new;$daemon->operationsFromWSDL($wsdl, handlers => { CallName => \&handle_call } );$daemon->run;

13

Other modules for XML::Compile

XML::Compile::TesterXML::Compile::DumperXML::Compile::Rewrite

XML::LibXML::Simple

xmlrewrite --plugin schema2001--xmlns xsd=$SCHEMA2001,me=$OTHER--no-annotations--no-comments--no-id-constraints--expand-includes--output reformated.xsd

To come:--no-elements version,bigone --extract-element--promote-unnamed 2 --no-unused-types--sort name ... etc ...

14

Publish XML Interface

Module based on XML::Compile::Cache

Include all versions of the schema in the package

Collect validated message examplescreate readers for them, and study the resultwhich types are really used? (what to declare)

Create constants for name-spaces

15

Example: Geo::KML

Geo::KML::Util

package Geo::KML::Util;use base 'Exporter';

my @kml21 = qw/NS_KML_21/;my @kml220 = qw/NS_KML_22 NS_ATOM_2005 NS_XAL_20/;

my @EXPORT = (@kml21, @kml220);my %EXPORT_TAGS = (kml21 => \@kml21, kml220 => \@kml22);

use constant NS_KML_21 => 'http://earth.google.com/kml/2.1';use constant NS_KML_22 => 'http://www.opengis.net/kml/2.2';use constant NS_ATOM_2005 => 'http://www.w3.org/2005/Atom';use constant NS_XAL_20 => 'urn:oasis:names:tc:ciq:xsdschema:xAL:2.0';

1;

16

Example: Geo::KML

Protocol version

package Geo::KML;use base 'XML::Compile::Cache';

use Geo::KML::Util; # all constants

my %ns2version = ( &NS_KML_21 => '2.1' , &NS_KML_22 => '2.2.0');my %version2ns = reverse %ns2version;

# ::Cache::new { (bless {},$class)->init(\%args) }sub init($){ my ($self, $args) = @_; my $version = $args->{version} or die; $class->SUPER::init($args); ...

use Geo::KML;my $kml = Geo::KML->new(version => '2.2.0');

17

Example: Geo::KML

Version specifics

my %info = ( '2.1' => { prefixes => [ '' => NS_KML_21 ] , schemas => [ 'kml-2.1/*.xsd' ] }

, '2.2.0' => { prefixes => [ '' => NS_KML_220, atom => NS_ATOM_2005 , xal => NS_XAL_20 ] , schemas => [ 'kml-2.2.0/*.xsd', 'atom-2005/*.xsd' , 'xal-2.0/*.xsd' ] } );

sub init($){ ... my $info = $info{$version} or die; $args->{prefixes} = $info->{prefixes}; $self->SUPER::init($args); ...

18

Example: Geo::KML

Compile schema's

$info{'2.2.0'}{schemas} = ['kml-2.2.0/*.xsd', ...];

sub init($){ ... $self->SUPER::init($args); (my $xsd = __FILE__) =~ s!\.pm$!/xsd!;

my $patterns = $info{$version}{schemas}; my @xsds = map {glob "$xsd/$_"} @$patterns;

$self->importDefinitions(\@xsds);

lib/Geo/KML.pmlib/Geo/KML/Util.pmlib/Geo/KML/xsd/atom-2005/atom-author-link.xsdlib/Geo/KML/xsd/kml-2.2.0/ogckml22.xsdlib/Geo/KML/xsd/xal-2.0/xAL.xsd

19

Example: Geo::KML

Read KML

sub init($){ ... $self->declare(READER => 'kml'); $self;}

sub readKML(@){ my ($class, $xml, %opts) = @_;

$xml->nodeName eq 'kml' or die; my $obj = $class->new(version => $xml->namespaceURI);

my $data = $obj->reader('kml')->($xml); return $data;

use Geo::KML;my ($type, $data) = Geo::KML->readKML('points.kmz');

name-space qualified!(empty prefix)

20

Example: Geo::KML

Write KML

$self->declare(WRITER => 'kml', include_namespaces => 1);

sub writeKML($$){ my ($self, $data, $filename) = @_;

my $doc = XML::LibXML::Document->new('1.0', 'UTF-8');

my $xml = $self->writer('kml')->($doc, $data);

$doc->setDocumentElement($xml); $doc->toFile($filename, 1);}

21

Example: Geo::KML

Write KML

use Geo::KML;

my %location = ( name => '' , description => '' , Point => {coordinates => [ "$long,$lat,0" ] } );

my %data = ( AbstractFeatureGroup => [ { Placemark => \%location }, ] );

my $kml = Geo::KML->new(version => '2.2.0');$kml->writeKML(\%data, 'example.kml');

22

Example: Geo::KML

... and then ...simplify access to the data-structure

my %typemap = ( "{$kml22}Document" => Geo::KML::Document );$self->declare(RW => 'kml', typemap => \%typemap);

package Geo::KML::Document; # shows default implem.

sub toXML($$){ my ($self, $type, $doc) = @_; $self; # XML data-structure or XML node}

sub fromXML($$){ my ($class, $data, $type) = @_; bless $data, $class;}