From XML (schema) to Application

22
2008-08- 13 MARKOV Solutions http://perl.overmeer.net Mark Overmeer [email protected] YAPC::EU 2008 From XML (schema) to Application

description

From XML (schema) to Application. From XML (schema) to Application. I HATE XML. Objective. XML schema's are very popular Schema/XML complications name-spaces strongly typed verbose notation often generated Application complications message validation: strictness schema location - PowerPoint PPT Presentation

Transcript of From XML (schema) to Application

Page 1: From XML (schema) to Application

2008-08-13

MARKOV Solutionshttp://perl.overmeer.net

Mark [email protected]

YAPC::EU 2008

From XML (schema) to Application

Page 2: From XML (schema) to Application

2008-08-13

MARKOV Solutionshttp://perl.overmeer.net

Mark [email protected]

YAPC::EU 2008

From XML (schema) to Application

I HATE XML

Page 3: From XML (schema) to Application

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!

Page 4: From XML (schema) to Application

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

Page 5: From XML (schema) to Application

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);

Page 6: From XML (schema) to Application

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;

Page 7: From XML (schema) to Application

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);

Page 8: From XML (schema) to Application

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

Page 9: From XML (schema) to Application

9

XML::Compile::Cache

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

Page 10: From XML (schema) to Application

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);

Page 11: From XML (schema) to Application

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);

Page 12: From XML (schema) to Application

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;

Page 13: From XML (schema) to Application

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 ...

Page 14: From XML (schema) to Application

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

Page 15: From XML (schema) to Application

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;

Page 16: From XML (schema) to Application

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');

Page 17: From XML (schema) to Application

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); ...

Page 18: From XML (schema) to Application

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

Page 19: From XML (schema) to Application

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)

Page 20: From XML (schema) to Application

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);}

Page 21: From XML (schema) to Application

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');

Page 22: From XML (schema) to Application

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;}