| POE-XUL documentation | Contained in the POE-XUL distribution. |
POE::XUL::RDF - RDF builder class
use POE::XUL::RDF;
my $data = [
'RDF:about' => "all-animals",
{ name => 'Lion', species => 'Panthera leo', class => 'Mammal',
'RDF:about' => "mammals/lion" },
{ name => 'Tarantula', species => 'Avicularia avicularia',
class => 'Arachnid',
'RDF:about' => "arachnids/tarantula" },
{ name => 'Hippopotamus', species => 'Hippopotamus amphibius',
class => 'Mammal',
'RDF:about' => 'mammals/hippopotamus'
}
];
my $rdf = POE::XUL::RDF->new( baseref => "http://some-url.com" );
$rdf->baserdf( 'rdf' );
$rdf->data( $data );
my $tree = Tree( datasources => $rdf,
ref => $ref->dataref
# ...
);
Primitive RDF generation for XUL trees.
my $rdf = POE::XUL::RDF->new( %params );
Creates a new object. %params may contain NS, baseref,
baserdf, dataref or data.
Namespace of the XML tags your data tuples will live in.
$rdf->baseref( $url );
$url = $rdf->baseref;
Get or set the base URL used to create baserdf, dataref and about.
$rdf->baserdf( $url );
$url = $rdf->baserdf;
Get or set the base URL of the data. Defaults to 'rdf' under baseref.
$rdf->baserdf( $url );
$tree->setAttribute( ref => $rdf->dataref );
Get or set the URL of the main data sequence. Can also be set if you have an RDF:about in your data.
$rdf->data( $AoH );
$AoH = $rdf->data;
Get or set the data contained in the RDF. POE::XUL::RDF only implements
a simplified data format. $AoH must be an arrayref of hashrefs. The
top arrayref is a RDF:Seq. Each hashref is an RDF:li. Keys are the
XML tags in the NS namespace. Values are text nodes. If a key name
begins with 'RDF:' it is placed as an attribute of the RDF:Description.
Example:
[ { city=>"Montreal", TZ=>"+5", 'RDF:note' => 'Something' },
{ city=>"Cochabamba", TZ=>"+4" }
]
Becomes roughly
<RDF:Seq>
<RDF:li><RDF:Description note="Something">
<NS:city>Montreal</NS:city>
<NS:TZ>+5</NS:TZ>
</RDF:Description></RDF:li>
<RDF:li><RDF:Description>
<NS:city>Cochabamba</NS:city>
<NS:TZ>+4</NS:TZ>
</RDF:Description></RDF:li>
</RDF:Seq>
RDF:about is a special attribute. Is is converted into an absolute URL with baseref.
What's more, if the first element in data is the string 'RDF:about',
the second element is used as the about attribute of the main RDF:Seq.
Example:
$rdf->baseref( 'http://example.com' );
$rdf->data( [ 'RDF:about' => 'some-cities',
{ city=>"Montreal", TZ=>"+5", 'RDF:about' => 'canada/mtl' },
] );
Becomes roughly:
<RDF:Seq about="http://example.com/some-cities>
<RDF:li><RDF:Description about="http://example.com/canada/mtl>
<NS:city>Montreal</NS:city>
<NS:TZ>+5</NS:TZ>
</RDF:Description></RDF:li>
</RDF:Seq>
my $frag = $rdf->fragment( $name );
Builds an URL that references $name fragment of the current RDF.
my $frag = $rdf->rdf_fragment( $name );
Builds an rdf: URL that references $name fragment of the current RDF. Useful for setting the sort attribute of a TreeCol, for example
TreeCol( id=>'TZ', sort=>$rdf->rdf_fragment( 'TZ' ) );
The following 3 methods are used to interface with the ChangeManager. You might want to overload them if you wish to define a new type of datasource. For example, a DBI datasource.
my $xml = $rdf->as_xml;
Convert the RDF to an XML string.
$resp->content_type( $rdf->mime_type );
Returns the MIME-type of the RDF. Defaults to 'application/rdf+xml'.
my $row = $rdf->index_of( $col, $value );
Search the the first tupple that has the $col column set to $value.
This is needed because if the user has sorted the data in the browser, the
Select event's selectedIndex will reference the row as seen on the screen,
not the row as present in the dataset.
Philip Gwyn <gwyn-at-cpan.org>
Copyright 2008-2010 by Philip Gwyn. All rights reserved;
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
| POE-XUL documentation | Contained in the POE-XUL distribution. |
package POE::XUL::RDF; # $Id$ # Copyright Philip Gwyn 2008-2010. All rights reserved. use strict; use warnings; use URI; use HTML::Entities qw( encode_entities_numeric ); our $VERSION = '0.0600'; ############################################################## sub new { my( $package, %init ) = @_; my $self = bless { data=>[] }, $package; # XXX: baseref from current server $self->baseref( $init{baseref} ) if $init{baseref}; $init{baserdf} ||= 'rdf'; $self->baserdf( $init{baserdf} ) if $init{baserdf}; $self->NS( $init{NS} ) if $init{NS}; $self->data( $init{data} ) if $init{data}; if( exists $init{dataref} ) { $self->dataref( $init{dataref} ); } elsif( ($self->{data}[0]||'') eq 'RDF:about' ) { $self->dataref( $self->{data}[1] ); } return $self; } ############################################################## sub fragment { my( $self, $name ) = @_; my $ret = URI->new( $self->{baserdf} ); $ret->fragment( $name ); return $ret; } sub rdf_fragment { my( $self, $name ) = @_; my $ret = $self->fragment( $name ); return "rdf:$ret"; } ############################################################## sub data { my( $self, $data ) = @_; return $self->{data} if 1==@_; $self->{data} = $data; } sub NS { my( $self, $NS ) = @_; return $self->{NS} if 1==@_; $self->{NS} = $NS; } sub baseref { my( $self, $baseref ) = @_; return $self->{baseref} if 1==@_; $self->{baseref} = URI->new( $baseref ); } sub baserdf { my( $self, $baserdf ) = @_; return $self->{baserdf} if 1==@_; if( $self->{baseref} ) { $self->{baserdf} = URI->new_abs( $baserdf, $self->{baseref} ); } else { $self->{baserdf} = URI->new( $baserdf ); } $self->{baserdf}->fragment( '' ); return $self->{baserdf}; } sub dataref { my( $self, $dataref ) = @_; return $self->{dataref} if 1==@_; if( $self->{baseref} ) { $self->{dataref} = URI->new_abs( $dataref, $self->{baseref} ); } else { $self->{dataref} = URI->new( $dataref ); } return $self->{dataref}; } ############################################################## sub mime_type { return 'application/rdf+xml'; } ############################################################## ## Linear search for the true row that was selected. sub index_of { my( $self, $col, $primary ) = @_; my $offset=0; for( my $q=0; $q <= $#{$self->{data}}; $q++ ) { if( not ref $self->{data}[$q] ) { $offset+=2; $q+=2; } next unless exists $self->{data}[$q]{$col} and $self->{data}[$q]{$col} eq $primary; return $q-$offset; } return -1; } ############################################################## sub as_xml { my( $self, $data ) = @_; $data ||= $self->{data}; my @Seq = ( 'RDF:Seq', {}, [] ); my @RDF = [ 'RDF:RDF', { 'xmlns:RDF' => "http://www.w3.org/1999/02/22-rdf-syntax-ns#", "xmlns:$self->{NS}" => $self->{baserdf} }, [ \@Seq ] ]; if( $data->[0] eq 'RDF:about' ) { $Seq[1]{about} = URI->new_abs( $data->[1], $self->{baseref} ); $data = [ @{ $data }[ 2..$#$data ] ]; } foreach my $row ( @$data ) { push @{ $Seq[2] }, [ 'RDF:li', {}, [[ 'RDF:Description', {}, [] ]] ]; my $li = $Seq[2][-1][2][0][2]; my $att = $Seq[2][-1][2][0][1]; while( my( $k, $v ) = each %$row ) { if( $k =~ /^RDF:(\w+)$/ ) { my $a = $1; if( $a eq 'about' ) { $att->{$a} = URI->new_abs( $v, $self->{baseref} ); } else { $att->{$a} = $v; } } else { push @$li, [ "$self->{NS}:$k", {}, [ $v ] ]; } } } # use Data::Dumper; # warn Dumper \@RDF; return $self->_rdf2xml( [@RDF], '' ); } ############################################################## sub _rdf2xml { my( $self, $rdf, $prefix ) = @_; my @ret; foreach my $el ( @$rdf ) { if( ref $el ) { push @ret, "$prefix<$el->[0]".$self->_att2xml( $el->[1] ); if( $el->[2] and @{ $el->[2] } ) { $ret[-1] .= ">"; if( ref $el->[2][0] ) { push @ret, $self->_rdf2xml( $el->[2], "$prefix " ); push @ret, "$prefix</$el->[0]>"; } else { $ret[-1] .= "$el->[2][0]</$el->[0]>"; } } else { $ret[-1] .= "/>"; } } else { push @ret, $el; } } return join "\n", @ret; } sub _att2xml { my( $self, $att ) = @_; return '' unless keys %$att; return join ' ', '', map { join '', encode_entities_numeric( $_, "\x00-\x1f<>&\'\x80-\xff" ), '="', encode_entities_numeric( $att->{$_}, "\x00-\x1f<>&\'\x80-\xff" ), '"' } keys %$att; } 1; __END__