=head1 NAME HTML::Microformats::Format::hResume - the hResume microformat =head1 SYNOPSIS use HTML::Microformats::DocumentContext; use HTML::Microformats::Format::hResume; my $context = HTML::Microformats::DocumentContext->new($dom, $uri); my @resumes = HTML::Microformats::Format::hResume->extract_all( $dom->documentElement, $context); foreach my $resume (@resumes) { print $resume->get_contact->get_fn . "\n"; } =head1 DESCRIPTION HTML::Microformats::Format::hResume inherits from HTML::Microformats::Format. See the base class definition for a description of property getter/setter methods, constructors, etc. =cut package HTML::Microformats::Format::hResume; use base qw(HTML::Microformats::Format HTML::Microformats::Mixin::Parser); use strict qw(subs vars); no warnings; use 5.010; use Object::AUTHORITY; BEGIN { $HTML::Microformats::Format::hResume::AUTHORITY = 'cpan:TOBYINK'; $HTML::Microformats::Format::hResume::VERSION = '0.105'; } sub new { my ($class, $element, $context, %options) = @_; my $cache = $context->cache; return $cache->get($context, $element, $class) if defined $cache && $cache->get($context, $element, $class); my $self = { 'element' => $element , 'context' => $context , 'cache' => $cache , 'id' => $context->make_bnode($element) , }; bless $self, $class; my $clone = $element->cloneNode(1); $self->_expand_patterns($clone); $self->_simple_parse($clone); $self->{'DATA'}->{'contact'} = $self->{'DATA'}->{'address'} unless defined $self->{'DATA'}->{'contact'}; if (defined $self->{'DATA'}->{'contact'}) { $self->{'id.holder'} = $self->{'DATA'}->{'contact'}->id(0, 'holder'); } else { $self->{'id.holder'} = $context->make_bnode; } # # Create links between hCard and hCalendar events found within! # foreach my $prop (qw(education experience)) # { # foreach my $e ( @{$self->{'DATA'}->{$prop}} ) # { # foreach my $ehc ( @{$self->{'DATA'}->{$prop.'-hcard'}} ) # { # my $ehcxp = $ehc->{'parent_property_node'}->getAttribute('data-cpan-html-microformats-nodepath'); # if ($ehcxp eq $e->{'parent_property_node'}->getAttribute('data-cpan-html-microformats-nodepath')) # { # $e -> {'associated_hcard'} = $ehc; # $ehc -> {'associated_hevent'} = $e; # } # } # } # # foreach my $card ( @{$self->{'DATA'}->{$prop.'-hcard'}} ) # { # $card->{'id.holder'} = $self->id(0, 'holder'); # } # # delete $self->{'DATA'}->{$prop.'-hcard'}; # } $cache->set($context, $element, $class, $self) if defined $cache; return $self; } sub format_signature { my $self = shift; my $cv = "http://purl.org/captsolo/resume-rdf/0.2/cv#"; my $cvx = "http://ontologi.es/hresume#"; # parsing hCards seems to do more harm than good! my $rv = { 'root' => 'hresume', 'classes' => [ ['summary', '?'], ['contact', 'm?', {'embedded'=>'hCard'}], ['address', 'tm?', {'embedded'=>'hCard'}], ['education', 'm*', {'embedded'=>'hEvent', 'allow-interleaved' => ['vcalendar']}], #}],, 'again-again'=>1}], #['education', 'm*', {'embedded'=>'hCard', 'allow-interleaved' => ['vcalendar', 'vevent'], 'use-key'=>'education-hcard'}], ['experience', 'm*', {'embedded'=>'hEvent', 'allow-interleaved' => ['vcalendar']}], #}],, 'again-again'=>1}], #['experience', 'm*', {'embedded'=>'hCard', 'allow-interleaved' => ['vcalendar', 'vevent'], 'use-key'=>'experience-hcard'}], ['skill', '*'], ['affiliation', 'M*', {'embedded'=>'hCard'}], ['cite', 't', {'use-key'=>'publication'}] ], 'options' => { }, 'rdf:type' => ["${cv}CV"] , 'rdf:property' => { 'summary' => { 'literal' => ["${cv}cvDescription"] }, 'experience' => { 'resource' => ["${cvx}experience"] }, 'education' => { 'resource' => ["${cvx}education"] }, 'contact' => { 'resource' => ["${cvx}contact"] }, 'affiliation' => { 'resource' => ["${cvx}affiliation"] }, 'publication' => { 'literal' => ["${cvx}publication"] }, 'skill' => { 'literal' => ["${cvx}skill"] }, }, }; return $rv; } sub add_to_model { my $self = shift; my $model = shift; $self->_simple_rdf($model); my $cv = "http://purl.org/captsolo/resume-rdf/0.2/cv#"; my $rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"; my $cvx = "http://ontologi.es/hresume#"; if (defined $self->data->{'contact'}) { $model->add_statement(RDF::Trine::Statement->new( $self->id(1), RDF::Trine::Node::Resource->new("${cv}aboutPerson"), $self->id(1, 'holder'), )); $self->data->{'contact'}->add_to_model($model); } foreach my $experience (@{$self->data->{'experience'}}) { $model->add_statement(RDF::Trine::Statement->new( $self->id(1), RDF::Trine::Node::Resource->new("${cv}hasWorkHistory"), $experience->id(1, 'experience'), )); $model->add_statement(RDF::Trine::Statement->new( $experience->id(1, 'experience'), RDF::Trine::Node::Resource->new("${rdf}type"), RDF::Trine::Node::Resource->new("${cv}WorkHistory"), )); $model->add_statement(RDF::Trine::Statement->new( $experience->id(1, 'experience'), RDF::Trine::Node::Resource->new("${cvx}ical-component"), $experience->id(1), )); $model->add_statement(RDF::Trine::Statement->new( $experience->id(1, 'experience'), RDF::Trine::Node::Resource->new("${cvx}business-card"), $experience->{'associated_vcard'}->id(1), )) if defined $experience->{'associated_vcard'}; $model->add_statement(RDF::Trine::Statement->new( $self->id(1, 'holder'), RDF::Trine::Node::Resource->new("http://purl.org/uF/hCard/terms/hasHistoricCard"), $experience->{'associated_vcard'}->id(1), )) if defined $experience->{'associated_vcard'}; $model->add_statement(RDF::Trine::Statement->new( $experience->id(1, 'experience'), RDF::Trine::Node::Resource->new("${cv}startDate"), $self->_make_literal($experience->data->{'dtstart'}, 'dateTime'), )) if defined $experience->data->{'dtstart'}; $model->add_statement(RDF::Trine::Statement->new( $experience->id(1, 'experience'), RDF::Trine::Node::Resource->new("${cv}endDate"), $self->_make_literal($experience->data->{'dtend'}, 'dateTime'), )) if defined $experience->data->{'dtend'}; if (defined $experience->{'associated_hcard'} && defined $experience->{'associated_hcard'}->data->{'title'}) { $model->add_statement(RDF::Trine::Statement->new( $experience->id(1, 'experience'), RDF::Trine::Node::Resource->new("${cv}jobTitle"), $self->_make_literal($experience->{'associated_hcard'}->data->{'title'}), )); } $experience->add_to_model($model); $experience->{'associated_hcard'}->add_to_model($model) if defined $experience->{'associated_hcard'}; } foreach my $edu (@{$self->data->{'education'}}) { $model->add_statement(RDF::Trine::Statement->new( $self->id(1), RDF::Trine::Node::Resource->new("${cv}hasEducation"), $edu->id(1, 'education'), )); $model->add_statement(RDF::Trine::Statement->new( $edu->id(1, 'education'), RDF::Trine::Node::Resource->new("${rdf}type"), RDF::Trine::Node::Resource->new("${cv}Education"), )); $model->add_statement(RDF::Trine::Statement->new( $edu->id(1, 'education'), RDF::Trine::Node::Resource->new("${cvx}ical-component"), $edu->id(1), )); $model->add_statement(RDF::Trine::Statement->new( $edu->id(1, 'education'), RDF::Trine::Node::Resource->new("${cvx}business-card"), $edu->{'associated_vcard'}->id(1), )) if defined $edu->{'associated_vcard'}; $model->add_statement(RDF::Trine::Statement->new( $self->id(1, 'holder'), RDF::Trine::Node::Resource->new("http://purl.org/uF/hCard/terms/hasHistoricCard"), $edu->{'associated_vcard'}->id(1), )) if defined $edu->{'associated_vcard'}; $model->add_statement(RDF::Trine::Statement->new( $edu->id(1, 'education'), RDF::Trine::Node::Resource->new("${cv}eduStartDate"), $self->_make_literal($edu->data->{'dtstart'}, 'dateTime'), )) if defined $edu->data->{'dtstart'}; $model->add_statement(RDF::Trine::Statement->new( $edu->id(1, 'education'), RDF::Trine::Node::Resource->new("${cv}eduGradDate"), $self->_make_literal($edu->data->{'dtend'}, 'dateTime'), )) if defined $edu->data->{'dtend'}; $edu->add_to_model($model); $edu->{'associated_hcard'}->add_to_model($model) if defined $edu->{'associated_hcard'}; } foreach my $skill (@{$self->data->{'skill'}}) { my $skill_bnode = $self->id(1, 'skill.'.$skill); $model->add_statement(RDF::Trine::Statement->new( $self->id(1), RDF::Trine::Node::Resource->new("${cv}hasSkill"), $skill_bnode, )); $model->add_statement(RDF::Trine::Statement->new( $skill_bnode, RDF::Trine::Node::Resource->new("${rdf}type"), RDF::Trine::Node::Resource->new("${cv}Skill"), )); $model->add_statement(RDF::Trine::Statement->new( $skill_bnode, RDF::Trine::Node::Resource->new("${cv}skillName"), $self->_make_literal($skill), )); } return $self; } sub profiles { my $class = shift; return qw(http://microformats.org/profile/hresume http://ufs.cc/x/hresume http://purl.org/uF/hResume/0.1/); } 1; =head1 MICROFORMAT HTML::Microformats::Format::hResume supports hResume as described at L. =head1 RDF OUTPUT The RDF output is modelled on Uldis Bojars' ResumeRDF Ontology L, with some additional terms from Toby Inkster's hResume vocab . =head1 BUGS Please report any bugs to L. =head1 SEE ALSO L, L, L, L. =head1 AUTHOR Toby Inkster Etobyink@cpan.orgE. =head1 COPYRIGHT AND LICENCE Copyright 2008-2012 Toby Inkster This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. =cut