BEGIN {
$RDF::RDFa::Parser::AUTHORITY
=
'cpan:TOBYINK'
;
$RDF::RDFa::Parser::VERSION
=
'1.097'
;
}
ERR_WARNING
=>
'w'
,
ERR_ERROR
=>
'e'
,
};
ERR_CODE_HOST
=>
'HOST01'
,
ERR_CODE_RDFXML_MUDDLE
=>
'RDFX01'
,
ERR_CODE_RDFXML_MESS
=>
'RDFX02'
,
ERR_CODE_PREFIX_BUILTIN
=>
'PRFX01'
,
ERR_CODE_PREFIX_ILLEGAL
=>
'PRFX02'
,
ERR_CODE_PREFIX_DISABLED
=>
'PRFX03'
,
ERR_CODE_INSTANCEOF_USED
=>
'INST01'
,
ERR_CODE_INSTANCEOF_OVERRULED
=>
'INST02'
,
ERR_CODE_CURIE_FELLTHROUGH
=>
'CURI01'
,
ERR_CODE_CURIE_UNDEFINED
=>
'CURI02'
,
ERR_CODE_BNODE_WRONGPLACE
=>
'BNOD01'
,
ERR_CODE_VOCAB_DISABLED
=>
'VOCA01'
,
ERR_CODE_LANG_INVALID
=>
'LANG01'
,
};
};
use
5.010;
our
$HAS_AWOL
;
BEGIN
{
local
$@;
eval
"use XML::Atom::OWL;"
;
$HAS_AWOL
= $@ ? 0 : 1;
}
sub
new
{
my
(
$class
,
$markup
,
$base_uri
,
$config
,
$store
)=
@_
;
if
(!
defined
$config
)
{
$config
= RDF::RDFa::Parser::Config->new; }
elsif
(blessed(
$config
) &&
$config
->isa(
'RDF::RDFa::Parser::Config'
))
{ 1; }
elsif
(
'HASH'
eq
ref
$config
)
{
$config
= RDF::RDFa::Parser::Config->new(
undef
,
undef
,
%$config
); }
else
{
die
"Unrecognised configuration\n"
; }
unless
(
$base_uri
=~ /^[a-z][a-z0-9\+\-\.]*:/i)
{
die
"Need a valid base URI.\n"
; }
Carp::croak(
"Need to provide markup to parse."
)
unless
defined
$markup
;
my
$dom
;
eval
{
if
(blessed(
$markup
) &&
$markup
->isa(
'XML::LibXML::Document'
))
{
$dom
=
$markup
;
$markup
=
$dom
->toString;
}
elsif
(
$config
->{
'dom_parser'
} =~ /^(opendocument|opendoc|odf|od|odt)$/i)
{
my
$parser
= RDF::RDFa::Parser::OpenDocumentObjectModel->new;
$dom
=
$parser
->parse_string(
$markup
,
$base_uri
);
}
elsif
(
$config
->{
'dom_parser'
} =~ /^(html|tagsoup|soup)$/i)
{
my
$parser
= HTML::HTML5::Parser->new;
$dom
= fix_document(
$parser
->parse_string(
$markup
) );
}
else
{
my
$parser
= XML::LibXML->new;
my
$catalogue
= dist_file(
'RDF-RDFa-Parser'
,
'catalogue/index.xml'
);
$parser
->load_catalog(
$catalogue
)
if
-r
$catalogue
;
$parser
->validation(0);
$dom
=
$parser
->parse_string(
$markup
);
}
};
$store
= RDF::Trine::Store::Memory->temporary_store
unless
defined
$store
;
my
$self
=
bless
{
baseuri
=>
$base_uri
,
origbase
=>
$base_uri
,
dom
=>
$dom
,
model
=> RDF::Trine::Model->new(
$store
),
bnodes
=> 0,
sub
=> {},
options
=>
$config
,
Graphs
=> {},
errors
=> [],
consumed
=> 0,
},
$class
;
$config
->auto_config(
$self
);
$self
->{options} =
$config
=
$config
->guess_rdfa_version(
$self
)
if
$config
->{guess_rdfa_version};
if
(
$dom
and
$self
->{options}{xhtml_base})
{
my
@bases
=
$self
->dom->getElementsByTagName(
'base'
);
my
$base
;
foreach
my
$b
(
@bases
)
{
if
(
$b
->hasAttribute(
'href'
))
{
$base
=
$b
->getAttribute(
'href'
);
$base
=~ s/
}
}
$self
->{baseuri} =
$self
->uri(
$base
)
if
defined
$base
&&
length
$base
;
}
return
$self
;
}
sub
new_from_url
{
my
(
$class
,
$url
,
$config
,
$store
)=
@_
;
my
$response
=
do
{
if
(blessed(
$url
) &&
$url
->isa(
'HTTP::Message'
))
{
$url
;
}
else
{
my
$ua
;
if
(blessed(
$config
) and
$config
->isa(
'RDF::RDFa::Parser::Config'
))
{
$ua
=
$config
->lwp_ua; }
elsif
(
ref
$config
eq
'HASH'
)
{
$ua
= RDF::RDFa::Parser::Config->new(
'xml'
,
undef
,
%$config
)->lwp_ua; }
else
{
$ua
= RDF::RDFa::Parser::Config->new(
'xml'
,
undef
)->lwp_ua; }
$ua
->get(
$url
);
}
};
my
$host
=
$response
->content_type;
if
(blessed(
$config
) and
$config
->isa(
'RDF::RDFa::Parser::Config'
))
{
$config
=
$config
->rehost(
$host
); }
elsif
(
ref
$config
eq
'HASH'
)
{
$config
= RDF::RDFa::Parser::Config->new(
$host
,
undef
,
%$config
); }
else
{
$config
= RDF::RDFa::Parser::Config->new(
$host
,
undef
); }
return
$class
->new(
$response
->decoded_content,
(
$response
->base ||
$url
).
''
,
$config
,
$store
,
);
}
*new_from_uri
= \
&new_from_url
;
*new_from_response
= \
&new_from_url
;
sub
graph
{
my
$self
=
shift
;
my
$graph
=
shift
;
$self
->consume;
if
(
defined
(
$graph
))
{
my
$tg
;
if
(
$graph
=~ m/^_:(.*)/)
{
$tg
= RDF::Trine::Node::Blank->new($1);
}
else
{
$tg
= RDF::Trine::Node::Resource->new(
$graph
,
$self
->{baseuri});
}
my
$m
= RDF::Trine::Model->temporary_model;
my
$i
=
$self
->{model}->get_statements(
undef
,
undef
,
undef
,
$tg
);
while
(
my
$statement
=
$i
->
next
)
{
$m
->add_statement(
$statement
);
}
return
$m
;
}
else
{
return
$self
->{model};
}
}
sub
output_graph
{
shift
->graph;
}
sub
graphs
{
my
$self
=
shift
;
$self
->consume;
my
@graphs
=
keys
(%{
$self
->{Graphs}});
my
%result
;
foreach
my
$graph
(
@graphs
)
{
$result
{
$graph
} =
$self
->graph(
$graph
);
}
return
\
%result
;
}
sub
opengraph
{
my
(
$self
,
$property
,
%opts
) =
@_
;
$self
->consume;
$property
= $1
$property
= $1
if
defined
$property
&&
$property
=~ m
'^http://ogp\.me/ns#(.*)$'
;
my
$rtp
;
if
(
defined
$property
&&
$property
=~ /^[a-z][a-z0-9\-\.\+]*:/i)
{
$rtp
= [ RDF::Trine::Node::Resource->new(
$property
) ];
}
elsif
(
defined
$property
)
{
$rtp
= [
];
}
my
$data
= {};
if
(
$rtp
)
{
foreach
my
$rtp2
(
@$rtp
)
{
my
$iter
=
$self
->graph->get_statements(
RDF::Trine::Node::Resource->new(
$self
->uri),
$rtp2
,
undef
);
while
(
my
$st
=
$iter
->
next
)
{
my
$propkey
=
$st
->predicate->uri;
$propkey
= $1
if
(
$st
->object->is_resource)
{
push
@{
$data
->{
$propkey
} },
$st
->object->uri; }
elsif
(
$st
->object->is_literal)
{
push
@{
$data
->{
$propkey
} },
$st
->object->literal_value; }
}
}
}
else
{
my
$iter
=
$self
->graph->get_statements(
RDF::Trine::Node::Resource->new(
$self
->uri),
undef
,
undef
);
while
(
my
$st
=
$iter
->
next
)
{
my
$propkey
=
$st
->predicate->uri;
$propkey
= $1
if
(
$st
->object->is_resource)
{
push
@{
$data
->{
$propkey
} },
$st
->object->uri; }
elsif
(
$st
->object->is_literal)
{
push
@{
$data
->{
$propkey
} },
$st
->object->literal_value; }
}
}
my
@return
;
if
(
defined
$property
)
{
@return
= @{
$data
->{
$property
}}
if
defined
$data
->{
$property
}; }
else
{
@return
=
keys
%$data
; }
return
wantarray
?
@return
:
$return
[0];
}
sub
dom
{
my
$self
=
shift
;
return
$self
->{dom};
}
sub
uri
{
my
$self
=
shift
;
my
$param
=
shift
||
''
;
my
$opts
=
shift
|| {};
if
((
ref
$opts
) =~ /^XML::LibXML/)
{
my
$x
= {
'element'
=>
$opts
};
$opts
=
$x
;
}
if
(
$param
=~ /^([a-z][a-z0-9\+\.\-]*)\:/i)
{
return
$param
;
}
elsif
(
$opts
->{
'require-absolute'
})
{
return
undef
;
}
my
$base
=
$self
->{baseuri};
if
(
$self
->{
'options'
}->{
'xml_base'
})
{
$base
=
$opts
->{
'xml_base'
} ||
$self
->{baseuri};
}
my
$rv
=
$self
->{options}{uri_class}->new_abs(
$param
,
$base
);
return
"$rv"
;
}
sub
errors
{
my
$self
=
shift
;
return
@{
$self
->{errors}};
}
sub
processor_graph
{
my
(
$self
,
$model
,
$context
) =
@_
;
$model
||= RDF::Trine::Model->new( RDF::Trine::Store->temporary_store );
my
$ERR
= RDF::Trine::Namespace->new(
'tag:buzzword.org.uk,2010:RDF-RDFa-Parser:error:'
);
my
$uuid
= Data::UUID->new;
my
$mkuri
=
sub
{
my
$id
=
$uuid
->create_str;
return
$ERR
->
$id
;
};
my
$st
=
sub
{
my
@n
=
map
{ blessed(
$_
) ?
$_
: RDF::Trine::Node::Literal->new(
$_
); }
@_
;
if
(
$context
)
{
$model
->add_statement(
RDF::Trine::Statement::Quad->new(
@n
,
$context
)
);
}
else
{
$model
->add_statement(
RDF::Trine::Statement->new(
@n
)
);
}
};
my
$typemap
= {(
ERR_CODE_HOST ,
'DocumentError'
,
ERR_CODE_RDFXML_MUDDLE ,
''
,
ERR_CODE_RDFXML_MESS ,
'DocumentError'
,
ERR_CODE_PREFIX_BUILTIN ,
'DocumentError'
,
ERR_CODE_PREFIX_ILLEGAL ,
'DocumentError'
,
ERR_CODE_PREFIX_DISABLED ,
''
,
ERR_CODE_INSTANCEOF_USED ,
''
,
ERR_CODE_INSTANCEOF_OVERRULED ,
''
,
ERR_CODE_CURIE_FELLTHROUGH ,
''
,
ERR_CODE_CURIE_UNDEFINED ,
'UnresolvedCURIE'
,
ERR_CODE_BNODE_WRONGPLACE ,
''
,
ERR_CODE_VOCAB_DISABLED ,
''
,
ERR_CODE_LANG_INVALID ,
'DocumentError'
,
)};
foreach
my
$err
(
$self
->errors)
{
my
$iri
=
$mkuri
->();
my
(
$level
,
$code
,
$message
,
$args
) =
@$err
;
if
(
$level
eq ERR_WARNING)
{
$st
->(
$iri
,
$RDF
->type,
$RDFA
->Warning);
}
elsif
(
$level
eq ERR_ERROR)
{
$st
->(
$iri
,
$RDF
->type,
$RDFA
->Error);
}
if
(
my
$class
=
$typemap
->{
$code
})
{
$st
->(
$iri
,
$RDF
->type,
$RDFA
->
$class
);
}
$st
->(
$iri
,
$DC
->description,
$message
);
if
(blessed(
$args
->{element}) and
$args
->{element}->can(
'nodePath'
))
{
my
$p_iri
=
$mkuri
->();
$st
->(
$iri
,
$RDFA
->context,
$p_iri
);
$st
->(
$p_iri
,
$RDF
->type,
$PTR
->XPathPointer);
$st
->(
$p_iri
,
$PTR
->expression,
$args
->{element}->nodePath);
}
}
return
$model
;
}
sub
processor_and_output_graph
{
my
$self
=
shift
;
my
$model
= RDF::Trine::Model->new;
$self
->
$_
->get_statements->
each
(
sub
{
$model
->add_statement(+
shift
) })
foreach
qw( processor_graph graph )
;
return
$model
;
}
sub
_log_error
{
my
(
$self
,
$level
,
$code
,
$message
,
%args
) =
@_
;
if
(
defined
$self
->{
'sub'
}->{
'onerror'
})
{
$self
->{
'sub'
}->{
'onerror'
}(
@_
);
}
elsif
(
$level
eq ERR_ERROR)
{
Carp::carp(
sprintf
(
"%04X: %s\n"
,
$code
,
$message
));
Carp::carp(
sprintf
(
"... with URI <%s>\n"
,
$args
{
'uri'
}))
if
defined
$args
{
'uri'
};
Carp::carp(
sprintf
(
"... on element '%s' with path '%s'\n"
,
$args
{
'element'
}->localname,
$args
{
'element'
}->nodePath))
if
blessed(
$args
{
'element'
}) &&
$args
{
'element'
}->isa(
'XML::LibXML::Node'
);
}
push
@{
$self
->{errors}}, [
$level
,
$code
,
$message
, \
%args
];
}
sub
consume
{
my
(
$self
,
%args
) =
@_
;
return
if
$self
->{
'consumed'
};
$self
->{
'consumed'
}++;
if
(!
$self
->{dom})
{
if
(
$args
{survive})
{
$self
->_log_error(
ERR_ERROR,
ERR_CODE_HOST,
'Input could not be parsed into a DOM!'
,
);
}
else
{
Carp::croak(
"Input could not be parsed into a DOM!"
);
}
return
$self
;
}
if
(
$self
->{options}{graph})
{
$self
->{options}{graph_attr} =
'graph'
unless
defined
$self
->{options}{graph_attr};
$self
->{options}{graph_type} =
'about'
unless
defined
$self
->{options}{graph_type};
$self
->{options}{graph_default} =
$self
->bnode
unless
defined
$self
->{options}{graph_default};
}
local
*XML::LibXML::Element::getAttributeNsSafe
=
sub
{
my
(
$element
,
$nsuri
,
$attribute
) =
@_
;
return
defined
$nsuri
?
$element
->getAttributeNS(
$nsuri
,
$attribute
) :
$element
->getAttribute(
$attribute
);
};
local
*XML::LibXML::Element::hasAttributeNsSafe
=
sub
{
my
(
$element
,
$nsuri
,
$attribute
) =
@_
;
return
defined
$nsuri
?
$element
->hasAttributeNS(
$nsuri
,
$attribute
) :
$element
->hasAttribute(
$attribute
);
};
$self
->_consume_element(
$self
->dom->documentElement, {
init
=> 1});
if
(
$self
->{options}{atom_parser} &&
$HAS_AWOL
)
{
my
$awol
= XML::Atom::OWL->new(
$self
->dom ,
$self
->uri ,
undef
,
$self
->{
'model'
} );
$awol
->{
'bnode_generator'
} =
$self
;
$awol
->set_callbacks(
$self
->{
'sub'
} );
$awol
->consume;
}
return
$self
;
}
sub
_consume_element
{
my
$self
=
shift
;
my
$current_element
=
shift
;
return
0
unless
$current_element
->nodeType == XML_ELEMENT_NODE;
my
$args
=
shift
;
my
(
$base
,
$parent_subject
,
$parent_subject_elem
,
$parent_object
,
$parent_object_elem
,
$list_mappings
,
$uri_mappings
,
$term_mappings
,
$incomplete_triples
,
$language
,
$graph
,
$graph_elem
,
$xml_base
);
if
(
$args
->{
'init'
})
{
my
$init
= RDF::RDFa::Parser::InitialContext->new(
$self
->{options}{initial_context},
);
$base
=
$self
->uri;
$parent_subject
=
$base
;
$parent_subject_elem
=
$self
->dom->documentElement;
$parent_object
=
undef
;
$parent_object_elem
=
undef
;
$uri_mappings
= +{
insensitive
=>
$init
->uri_mappings };
$term_mappings
= +{
insensitive
=>
$init
->term_mappings };
$incomplete_triples
= [];
$list_mappings
= {};
$language
=
undef
;
$graph
=
$self
->{options}{graph} ?
$self
->{options}{graph_default} :
undef
;
$graph_elem
=
undef
;
$xml_base
=
undef
;
if
(
$self
->{options}{vocab_default})
{
$uri_mappings
->{
'(VOCAB)'
} =
$self
->{options}{vocab_default};
}
if
(
$self
->{options}{prefix_default})
{
$uri_mappings
->{
'(DEFAULT PREFIX)'
} =
$self
->{options}{prefix_default};
}
}
else
{
$base
=
$args
->{
'base'
};
$parent_subject
=
$args
->{
'parent_subject'
};
$parent_subject_elem
=
$args
->{
'parent_subject_elem'
};
$parent_object
=
$args
->{
'parent_object'
};
$parent_object_elem
=
$args
->{
'parent_object_elem'
};
$uri_mappings
= dclone(
$args
->{
'uri_mappings'
});
$term_mappings
= dclone(
$args
->{
'term_mappings'
});
$incomplete_triples
=
$args
->{
'incomplete_triples'
};
$list_mappings
=
$args
->{
'list_mappings'
};
$language
=
$args
->{
'language'
};
$graph
=
$args
->{
'graph'
};
$graph_elem
=
$args
->{
'graph_elem'
};
$xml_base
=
$args
->{
'xml_base'
};
}
my
$rdfans
=
$self
->{options}{ns} ||
undef
;
my
$recurse
= 1;
my
$skip_element
= 0;
my
$new_subject
=
undef
;
my
$new_subject_elem
=
undef
;
my
$current_object_resource
=
undef
;
my
$current_object_resource_elem
=
undef
;
my
$typed_resource
=
undef
;
my
$typed_resource_elem
=
undef
;
my
$local_uri_mappings
=
$uri_mappings
;
my
$local_term_mappings
=
$term_mappings
;
my
$local_incomplete_triples
= [];
my
$current_language
=
$language
;
my
$activity
= 0;
if
(
$self
->{options}{xhtml_lang}
&&
$current_element
->hasAttribute(
'lang'
))
{
if
(
$self
->_valid_lang(
$current_element
->getAttribute(
'lang'
) ))
{
$current_language
=
$current_element
->getAttribute(
'lang'
);
}
else
{
$self
->_log_error(
ERR_WARNING,
ERR_CODE_LANG_INVALID,
sprintf
(
'Language code "%s" is not valid.'
,
$current_element
->getAtrribute(
'lang'
)),
element
=>
$current_element
,
lang
=>
$current_element
->getAttribute(
'lang'
),
)
if
$@;
}
}
if
(
$self
->{options}{xml_lang}
&&
$current_element
->hasAttributeNsSafe(XML_XML_NS,
'lang'
))
{
if
(
$self
->_valid_lang(
$current_element
->getAttributeNsSafe(XML_XML_NS,
'lang'
) ))
{
$current_language
=
$current_element
->getAttributeNsSafe(XML_XML_NS,
'lang'
);
}
else
{
$self
->_log_error(
ERR_WARNING,
ERR_CODE_LANG_INVALID,
sprintf
(
'Language code "%s" is not valid.'
,
$current_element
->getAttributeNsSafe(XML_XML_NS,
'lang'
)),
element
=>
$current_element
,
lang
=>
$current_element
->getAttributeNsSafe(XML_XML_NS,
'lang'
),
)
if
$@;
}
}
if
(
$current_element
->hasAttributeNsSafe(XML_XML_NS,
'base'
))
{
my
$old_base
=
$xml_base
;
$xml_base
=
$current_element
->getAttributeNsSafe(XML_XML_NS,
'base'
);
$xml_base
=~ s/
$xml_base
=
$self
->uri(
$xml_base
,
{
'element'
=>
$current_element
,
'xml_base'
=>
$old_base
});
}
my
$hrefsrc_base
=
$base
;
if
(
$self
->{options}{xml_base}==2 &&
defined
$xml_base
)
{
$hrefsrc_base
=
$xml_base
;
}
if
(
$self
->{options}{embedded_rdfxml}
&&
$current_element
->localname eq
'RDF'
{
return
1
if
$self
->{options}{embedded_rdfxml}==2;
my
$g
=
$graph
;
unless
(
$self
->{options}{embedded_rdfxml} == 3)
{
$g
=
$self
->bnode;
}
my
$fake_lang
= 0;
unless
(
$current_element
->hasAttributeNsSafe(XML_XML_NS,
'lang'
))
{
$current_element
->setAttributeNS(XML_XML_NS,
'lang'
,
$current_language
);
$fake_lang
= 1;
}
my
$rdfxml_base
=
$self
->{
'origbase'
};
$rdfxml_base
=
$base
if
$self
->{options}{xhtml_base}==2;
$rdfxml_base
=
$xml_base
if
defined
$xml_base
;
eval
{
my
$_map
;
my
$bnode_mapper
=
sub
{
my
$orig
=
shift
;
$_map
->{
$orig
} =
$self
->bnode
unless
defined
$_map
->{
$orig
};
return
$_map
->{
$orig
};
};
my
$parser
= RDF::Trine::Parser->new(
'rdfxml'
);
my
$r
=
$parser
->parse(
$rdfxml_base
,
$current_element
->toStringEC14N,
sub
{
my
$st
=
shift
;
my
(
$s
,
$p
,
@o
);
$s
=
$st
->subject->is_blank ?
$bnode_mapper
->(
$st
->subject->blank_identifier) :
$st
->subject->uri_value ;
$p
=
$st
->predicate->uri_value ;
if
(
$st
->object->is_literal)
{
@o
= (
$st
->object->literal_value,
$st
->object->literal_datatype,
$st
->object->literal_value_language,
);
$self
->_insert_triple_literal({
current
=>
$current_element
},
$s
,
$p
,
@o
,
(
$self
->{options}{graph} ?
$g
:
undef
));
}
else
{
push
@o
,
$st
->object->is_blank ?
$bnode_mapper
->(
$st
->object->blank_identifier) :
$st
->object->uri_value;
$self
->_insert_triple_resource({
current
=>
$current_element
},
$s
,
$p
,
@o
,
(
$self
->{options}{graph} ?
$g
:
undef
));
}
});
};
$self
->_log_error(
ERR_ERROR,
ERR_CODE_RDFXML_MESS,
"Could not parse embedded RDF/XML content: ${@}"
,
element
=>
$current_element
,
)
if
$@;
$current_element
->removeAttributeNS(XML_XML_NS,
'lang'
)
if
(
$fake_lang
);
return
1;
}
elsif
(
$current_element
->localname eq
'RDF'
{
$self
->_log_error(
ERR_WARNING,
ERR_CODE_RDFXML_MUDDLE,
'Encountered embedded RDF/XML content, but not configured to parse or skip it.'
,
element
=>
$current_element
,
);
}
if
(
$self
->{
'options'
}->{
'xmlns_attr'
})
{
foreach
my
$A
(
$current_element
->getAttributes)
{
my
$attr
=
$A
->getName;
if
(
$attr
=~ /^xmlns\:(.+)$/i)
{
my
$pfx
=
$self
->{
'options'
}->{
'prefix_nocase_xmlns'
} ? (
lc
$1) : $1;
my
$cls
=
$self
->{
'options'
}->{
'prefix_nocase_xmlns'
} ?
'insensitive'
:
'sensitive'
;
my
$uri
=
$A
->getValue;
if
(
$pfx
=~ /^(xml|xmlns|_)$/i)
{
$self
->_log_error(
ERR_ERROR,
ERR_CODE_PREFIX_BUILTIN,
"Attempt to redefine built-in CURIE prefix '$pfx' not allowed."
,
element
=>
$current_element
,
prefix
=>
$pfx
,
uri
=>
$uri
,
);
}
elsif
(
$pfx
!~ /^(
$XML::RegExp::NCName
)$/)
{
$self
->_log_error(
ERR_ERROR,
ERR_CODE_PREFIX_ILLEGAL,
"Attempt to define non-NCName CURIE prefix '$pfx' not allowed."
,
element
=>
$current_element
,
prefix
=>
$pfx
,
uri
=>
$uri
,
);
}
elsif
(
$uri
eq XML_XML_NS ||
$uri
eq XML_XMLNS_NS)
{
$self
->_log_error(
ERR_ERROR,
ERR_CODE_PREFIX_BUILTIN,
"Attempt to define any CURIE prefix for '$uri' not allowed using \@xmlns."
,
element
=>
$current_element
,
prefix
=>
$pfx
,
uri
=>
$uri
,
);
}
else
{
$self
->{
'sub'
}->{
'onprefix'
}(
$self
,
$current_element
,
$pfx
,
$uri
,
$cls
)
if
defined
$self
->{
'sub'
}->{
'onprefix'
};
$local_uri_mappings
->{
$cls
}->{
$pfx
} =
$uri
;
}
}
}
}
if
(
$self
->{
'options'
}->{
'prefix_attr'
}
&&
$current_element
->hasAttributeNsSafe(
$rdfans
,
'prefix'
))
{
my
$pfx_attr
=
$current_element
->getAttributeNsSafe(
$rdfans
,
'prefix'
) .
' '
;
my
@bits
=
split
/[\s\r\n]+/,
$pfx_attr
;
while
(
@bits
)
{
my
(
$bit1
,
$bit2
,
@rest
) =
@bits
;
@bits
=
@rest
;
$bit1
=~ s/:$//;
my
$pfx
=
$self
->{
'options'
}->{
'prefix_nocase_attr'
} ? (
lc
$bit1
) :
$bit1
;
my
$cls
=
$self
->{
'options'
}->{
'prefix_nocase_attr'
} ?
'insensitive'
:
'sensitive'
;
my
$uri
=
$bit2
;
unless
(
$pfx
=~ /^
$XML::RegExp::NCName
$/)
{
$self
->_log_error(
ERR_ERROR,
ERR_CODE_PREFIX_ILLEGAL,
"Attempt to define non-NCName CURIE prefix '$pfx' not allowed."
,
element
=>
$current_element
,
prefix
=>
$pfx
,
uri
=>
$uri
,
);
next
;
}
$self
->{
'sub'
}->{
'onprefix'
}(
$self
,
$current_element
,
$pfx
,
$uri
,
$cls
)
if
defined
$self
->{
'sub'
}->{
'onprefix'
};
$local_uri_mappings
->{
$cls
}->{
$pfx
} =
$uri
;
}
}
elsif
(
$current_element
->hasAttributeNsSafe(
$rdfans
,
'prefix'
))
{
$self
->_log_error(
ERR_WARNING,
ERR_CODE_PREFIX_DISABLED,
"\@prefix found, but support disabled."
,
element
=>
$current_element
,
);
}
if
(
$self
->{options}{vocab_attr}
&&
$current_element
->hasAttributeNsSafe(
$rdfans
,
'vocab'
))
{
if
(
$current_element
->getAttributeNsSafe(
$rdfans
,
'vocab'
) eq
''
)
{
$local_uri_mappings
->{
'(VOCAB)'
} =
$self
->{options}{vocab_default};
}
else
{
$local_uri_mappings
->{
'(VOCAB)'
} =
$self
->uri(
$current_element
->getAttributeNsSafe(
$rdfans
,
'vocab'
),
{
'element'
=>
$current_element
,
'xml_base'
=>
$xml_base
});
}
}
elsif
(
$current_element
->hasAttributeNsSafe(
$rdfans
,
'vocab'
))
{
$self
->_log_error(
ERR_WARNING,
ERR_CODE_VOCAB_DISABLED,
"\@vocab found, but support disabled."
,
element
=>
$current_element
,
uri
=>
$self
->uri(
$current_element
->getAttributeNsSafe(
$rdfans
,
'vocab'
),
{
'element'
=>
$current_element
,
'xml_base'
=>
$xml_base
}),
);
}
if
(
$self
->{
'options'
}->{
'graph'
})
{
my
(
$xmlns
,
$attr
) = (
$self
->{
'options'
}->{
'graph_attr'
} =~ /^(?:\{(.+)\})?(.+)$/);
unless
(
$attr
)
{
$xmlns
=
$rdfans
;
$attr
=
'graph'
;
}
if
(
$self
->{
'options'
}->{
'graph_type'
} eq
'id'
&&
$current_element
->hasAttributeNsSafe(
$xmlns
,
$attr
))
{
$graph
=
$self
->uri(
'#'
.
$current_element
->getAttributeNsSafe(
$xmlns
,
$attr
),
{
'element'
=>
$current_element
,
'xml_base'
=>
$hrefsrc_base
});
}
elsif
(
$self
->{
'options'
}->{
'graph_type'
} eq
'about'
&&
$current_element
->hasAttributeNsSafe(
$xmlns
,
$attr
))
{
$graph
=
$self
->_expand_curie(
$current_element
->getAttributeNsSafe(
$xmlns
,
$attr
),
element
=>
$current_element
,
attribute
=>
'graph'
,
prefixes
=>
$local_uri_mappings
,
terms
=>
$local_term_mappings
,
xml_base
=>
$xml_base
,
);
$graph
=
$self
->{
'options'
}->{
'graph_default'
}
unless
defined
$graph
;
}
}
if
(
$self
->{options}{vocab_triple}
and
$self
->{options}{vocab_attr}
and
$current_element
->hasAttributeNsSafe(
$rdfans
,
'vocab'
)
and
defined
$local_uri_mappings
->{
'(VOCAB)'
})
{
$self
->_insert_triple_resource({
current
=>
$current_element
,
subject
=>
$current_element
->ownerDocument->documentElement,
predicate
=>
$current_element
,
object
=>
$current_element
,
graph
=>
$graph_elem
,
},
$base
,
$local_uri_mappings
->{
'(VOCAB)'
},
$graph
);
}
if
(
$self
->{
'options'
}->{
'role_attr'
}
&&
$current_element
->hasAttributeNsSafe(
$rdfans
,
'role'
))
{
my
@role
=
$self
->_split_tokens(
$current_element
->getAttributeNsSafe(
$rdfans
,
'role'
) );
my
@ROLE
=
map
{
my
$x
=
$self
->_expand_curie(
$_
,
element
=>
$current_element
,
attribute
=>
'role'
,
prefixes
=>
$local_uri_mappings
,
terms
=>
$local_term_mappings
,
xml_base
=>
$xml_base
,
);
defined
$x
? (
$x
) : ();
}
@role
;
if
(
@ROLE
)
{
if
(
$current_element
->hasAttribute(
'id'
)
and !
defined
$self
->{element_subjects}->{
$current_element
->nodePath})
{
$self
->{element_subjects}->{
$current_element
->nodePath} =
$self
->uri(
sprintf
(
'#%s'
,
$current_element
->getAttribute(
'id'
)),
{
'element'
=>
$current_element
,
'xml_base'
=>
$hrefsrc_base
});
}
elsif
(!
defined
$self
->{element_subjects}->{
$current_element
->nodePath})
{
$self
->{element_subjects}->{
$current_element
->nodePath} =
$self
->bnode;
}
foreach
my
$r
(
@ROLE
)
{
my
$E
= {
current
=>
$current_element
,
subject
=>
$current_element
,
predicate
=>
$current_element
,
object
=>
$current_element
,
graph
=>
$graph_elem
,
};
}
}
}
if
(
$self
->{
'options'
}->{
'cite_attr'
}
&&
$current_element
->hasAttributeNsSafe(
$rdfans
,
'cite'
))
{
my
$citation
=
$self
->uri(
$current_element
->getAttributeNsSafe(
$rdfans
,
'cite'
),
{
'element'
=>
$current_element
,
'xml_base'
=>
$hrefsrc_base
}
);
if
(
defined
$citation
)
{
if
(
$current_element
->hasAttribute(
'id'
)
and !
defined
$self
->{element_subjects}->{
$current_element
->nodePath})
{
$self
->{element_subjects}->{
$current_element
->nodePath} =
$self
->uri(
sprintf
(
'#%s'
,
$current_element
->getAttribute(
'id'
)),
{
'element'
=>
$current_element
,
'xml_base'
=>
$hrefsrc_base
});
}
elsif
(!
defined
$self
->{element_subjects}->{
$current_element
->nodePath})
{
$self
->{element_subjects}->{
$current_element
->nodePath} =
$self
->bnode;
}
my
$E
= {
current
=>
$current_element
,
subject
=>
$current_element
,
predicate
=>
$current_element
,
object
=>
$current_element
,
graph
=>
$graph_elem
,
};
}
}
my
@rel
=
$self
->_split_tokens(
$current_element
->getAttributeNsSafe(
$rdfans
,
'rel'
) );
my
@rev
=
$self
->_split_tokens(
$current_element
->getAttributeNsSafe(
$rdfans
,
'rev'
) );
if
(
$self
->{options}{alt_stylesheet}
&& (
grep
/^alternate$/i,
@rel
)
&& (
grep
/^stylesheet$/i,
@rel
))
{
@rel
=
grep
!/^(alternate|stylesheet)$/i,
@rel
;
push
@rel
,
':ALTERNATE-STYLESHEET'
;
}
my
@REL
=
map
{
my
$x
=
$self
->_expand_curie(
$_
,
element
=>
$current_element
,
attribute
=>
'rel'
,
prefixes
=>
$local_uri_mappings
,
terms
=>
$local_term_mappings
,
xml_base
=>
$xml_base
,
);
defined
$x
? (
$x
) : ();
}
@rel
;
my
@REV
=
map
{
my
$x
=
$self
->_expand_curie(
$_
,
element
=>
$current_element
,
attribute
=>
'rev'
,
prefixes
=>
$local_uri_mappings
,
terms
=>
$local_term_mappings
,
xml_base
=>
$xml_base
,
);
defined
$x
? (
$x
) : ();
}
@rev
;
my
$NEW_SUBJECT_ATTR_ABOUT
=
sub
{
if
(
$current_element
->hasAttributeNsSafe(
$rdfans
,
'about'
))
{
my
$s
=
$self
->_expand_curie(
$current_element
->getAttributeNsSafe(
$rdfans
,
'about'
),
element
=>
$current_element
,
attribute
=>
'about'
,
prefixes
=>
$local_uri_mappings
,
terms
=>
$local_term_mappings
,
xml_base
=>
$xml_base
,
);
my
$e
=
$current_element
;
return
(
$s
,
$e
);
}
return
;
};
my
$NEW_SUBJECT_ATTR_SRC
=
sub
{
if
(
$current_element
->hasAttributeNsSafe(
$rdfans
,
'src'
))
{
my
$s
=
$self
->uri(
$current_element
->getAttributeNsSafe(
$rdfans
,
'src'
),
{
'element'
=>
$current_element
,
'xml_base'
=>
$hrefsrc_base
}
);
my
$e
=
$current_element
;
return
(
$s
,
$e
);
}
return
;
};
my
$NEW_SUBJECT_DEFAULTS
=
sub
{
if
(
$current_element
==
$current_element
->ownerDocument->documentElement)
{
return
(
$self
->uri(
undef
, {
'element'
=>
$current_element
,
'xml_base'
=>
$hrefsrc_base
}),
$current_element
);
}
if
(
$self
->{options}{xhtml_elements}
&& (
$current_element
->tagName eq
'head'
||
$current_element
->tagName eq
'body'
))
{
return
(
$parent_object
,
$parent_object_elem
)
if
$self
->{options}{xhtml_elements}==2;
return
(
$self
->uri(
undef
, {
'element'
=>
$current_element
,
'xml_base'
=>
$hrefsrc_base
}),
$current_element
);
}
if
(
$self
->{options}{atom_elements}
&& (
$current_element
->tagName eq
'feed'
||
$current_element
->tagName eq
'entry'
))
{
return
(
$self
->_atom_magic(
$current_element
),
$current_element
);
}
return
;
};
my
$NEW_SUBJECT_INHERIT
=
sub
{
$skip_element
= 1
if
shift
&& not
$current_element
->hasAttributeNsSafe(
$rdfans
,
'property'
);
return
(
$parent_object
,
$parent_object_elem
)
if
$parent_object
;
return
;
};
my
$NEW_SUBJECT_ATTR_RESOURCE
=
sub
{
if
(
$current_element
->hasAttributeNsSafe(
$rdfans
,
'resource'
))
{
my
$s
=
$self
->_expand_curie(
$current_element
->getAttributeNsSafe(
$rdfans
,
'resource'
),
element
=>
$current_element
,
attribute
=>
'resource'
,
prefixes
=>
$local_uri_mappings
,
terms
=>
$local_term_mappings
,
xml_base
=>
$xml_base
,
);
return
(
$s
,
$current_element
);
}
return
;
};
my
$NEW_SUBJECT_ATTR_HREF
=
sub
{
if
(
$current_element
->hasAttributeNsSafe(
$rdfans
,
'href'
))
{
my
$s
=
$self
->uri(
$current_element
->getAttributeNsSafe(
$rdfans
,
'href'
),
{
'element'
=>
$current_element
,
'xml_base'
=>
$hrefsrc_base
}
);
return
(
$s
,
$current_element
);
}
return
;
};
my
$NEW_SUBJECT_ATTR_TYPEOF
=
sub
{
if
(
$current_element
->hasAttributeNsSafe(
$rdfans
,
'typeof'
)
or
$current_element
->hasAttributeNsSafe(
$rdfans
,
'instanceof'
))
{
if
(
$current_element
->hasAttributeNsSafe(
$rdfans
,
'instanceof'
)
and not
$current_element
->hasAttributeNsSafe(
$rdfans
,
'typeof'
))
{
$self
->_log_error(
ERR_WARNING,
ERR_CODE_INSTANCEOF_USED,
"Deprecated \@instanceof found; using it anyway."
,
element
=>
$current_element
,
);
}
return
(
$self
->bnode(
$current_element
),
$current_element
);
}
return
;
};
if
(!
$current_element
->hasAttributeNsSafe(
$rdfans
,
'rel'
)
and !
$current_element
->hasAttributeNsSafe(
$rdfans
,
'rev'
)
and
$current_element
->hasAttributeNsSafe(
$rdfans
,
'property'
)
and !
$current_element
->hasAttributeNsSafe(
$rdfans
,
'datatype'
)
and !
$current_element
->hasAttributeNsSafe(
$rdfans
,
'content'
)
and
$self
->{options}{property_resources})
{
foreach
my
$code
(
$NEW_SUBJECT_ATTR_ABOUT
,
(
$NEW_SUBJECT_ATTR_SRC
) x!
$self
->{options}{src_sets_object},
$NEW_SUBJECT_DEFAULTS
,
$NEW_SUBJECT_INHERIT
,
) {
(
$new_subject
,
$new_subject_elem
) =
$code
->()
unless
$new_subject
;
}
if
(
$current_element
->hasAttributeNsSafe(
$rdfans
,
'typeof'
)
or
$current_element
->hasAttributeNsSafe(
$rdfans
,
'instanceof'
))
{
foreach
my
$code
(
$NEW_SUBJECT_ATTR_ABOUT
,
(
$NEW_SUBJECT_ATTR_SRC
) x!
$self
->{options}{src_sets_object},
$NEW_SUBJECT_DEFAULTS
,
) {
(
$typed_resource
,
$typed_resource_elem
) =
$code
->()
unless
$typed_resource
;
}
unless
(
$typed_resource
)
{
foreach
my
$code
(
$NEW_SUBJECT_ATTR_RESOURCE
,
$NEW_SUBJECT_ATTR_HREF
,
(
$NEW_SUBJECT_ATTR_SRC
) x!!
$self
->{options}{src_sets_object},
) {
(
$typed_resource
,
$typed_resource_elem
) =
$code
->()
unless
$typed_resource
;
}
unless
(
$typed_resource
)
{
(
$typed_resource
,
$typed_resource_elem
) =
(
$self
->bnode(
$current_element
),
$current_element
);
}
(
$current_object_resource
,
$current_object_resource_elem
) =
(
$typed_resource
,
$typed_resource_elem
);
}
}
}
elsif
(!
$current_element
->hasAttributeNsSafe(
$rdfans
,
'rel'
)
and !
$current_element
->hasAttributeNsSafe(
$rdfans
,
'rev'
))
{
my
$i
;
foreach
my
$code
(
$NEW_SUBJECT_ATTR_ABOUT
,
(
$NEW_SUBJECT_ATTR_SRC
) x!
$self
->{options}{src_sets_object},
$NEW_SUBJECT_ATTR_RESOURCE
,
$NEW_SUBJECT_ATTR_HREF
,
(
$NEW_SUBJECT_ATTR_SRC
) x!!
$self
->{options}{src_sets_object},
$NEW_SUBJECT_DEFAULTS
,
$NEW_SUBJECT_ATTR_TYPEOF
,
sub
{
$NEW_SUBJECT_INHERIT
->(1) },
) {
last
if
$new_subject
;
(
$new_subject
,
$new_subject_elem
) =
$code
->();
}
if
(
$current_element
->hasAttributeNsSafe(
$rdfans
,
'typeof'
)
or
$current_element
->hasAttributeNsSafe(
$rdfans
,
'instanceof'
))
{
(
$typed_resource
,
$typed_resource_elem
) = (
$new_subject
,
$new_subject_elem
);
}
}
else
{
foreach
my
$code
(
$NEW_SUBJECT_ATTR_ABOUT
,
(
$NEW_SUBJECT_ATTR_SRC
) x!
$self
->{options}{src_sets_object},
(
$NEW_SUBJECT_ATTR_TYPEOF
) x!
$self
->{options}{typeof_resources},
$NEW_SUBJECT_DEFAULTS
,
$NEW_SUBJECT_INHERIT
,
) {
(
$new_subject
,
$new_subject_elem
) =
$code
->()
unless
$new_subject
;
}
foreach
my
$code
(
$NEW_SUBJECT_ATTR_RESOURCE
,
$NEW_SUBJECT_ATTR_HREF
,
(
$NEW_SUBJECT_ATTR_SRC
) x!!
$self
->{options}{src_sets_object},
) {
(
$current_object_resource
,
$current_object_resource_elem
) =
$code
->()
unless
$current_object_resource
;
}
if
(
$current_element
->hasAttributeNsSafe(
$rdfans
,
'typeof'
)
or
$current_element
->hasAttributeNsSafe(
$rdfans
,
'instanceof'
))
{
if
(
$current_element
->hasAttributeNsSafe(
$rdfans
,
'about'
))
{
(
$typed_resource
,
$typed_resource_elem
) = (
$new_subject
,
$new_subject_elem
);
}
elsif
(
$self
->{options}{typeof_resources})
{
(
$current_object_resource
,
$current_object_resource_elem
) =
(
$self
->bnode(
$current_element
),
$current_element
)
unless
$current_object_resource
;
(
$typed_resource
,
$typed_resource_elem
) = (
$current_object_resource
,
$current_object_resource_elem
);
}
else
{
(
$typed_resource
,
$typed_resource_elem
) = (
$new_subject
,
$new_subject_elem
);
}
}
}
if
(
$typed_resource
&& (
$current_element
->hasAttributeNsSafe(
$rdfans
,
'instanceof'
)
||
$current_element
->hasAttributeNsSafe(
$rdfans
,
'typeof'
)))
{
if
(
$current_element
->hasAttributeNsSafe(
$rdfans
,
'instanceof'
)
&&
$current_element
->hasAttributeNsSafe(
$rdfans
,
'typeof'
))
{
$self
->_log_error(
ERR_WARNING,
ERR_CODE_INSTANCEOF_OVERRULED,
"Deprecated \@instanceof found; ignored because \@typeof also present."
,
element
=>
$current_element
,
);
}
elsif
(
$current_element
->hasAttributeNsSafe(
$rdfans
,
'instanceof'
))
{
$self
->_log_error(
ERR_WARNING,
ERR_CODE_INSTANCEOF_USED,
"Deprecated \@instanceof found; using it anyway."
,
element
=>
$current_element
,
);
}
my
@instanceof
=
$self
->_split_tokens(
$current_element
->getAttributeNsSafe(
$rdfans
,
'typeof'
)
||
$current_element
->getAttributeNsSafe(
$rdfans
,
'instanceof'
) );
foreach
my
$curie
(
@instanceof
)
{
my
$rdftype
=
$self
->_expand_curie(
$curie
,
element
=>
$current_element
,
attribute
=>
'typeof'
,
prefixes
=>
$local_uri_mappings
,
terms
=>
$local_term_mappings
,
xml_base
=>
$xml_base
,
);
next
unless
defined
$rdftype
;
my
$E
= {
current
=>
$current_element
,
subject
=>
$typed_resource_elem
,
predicate
=>
$current_element
,
object
=>
$current_element
,
graph
=>
$graph_elem
,
};
$self
->_insert_triple_resource(
$E
,
$typed_resource
, RDF_TYPE,
$rdftype
,
$graph
);
$activity
++;
}
}
if
(
$self
->{
'options'
}->{
'longdesc_attr'
}
&&
$current_element
->hasAttributeNsSafe(
$rdfans
,
'longdesc'
))
{
my
$longdesc
=
$self
->uri(
$current_element
->getAttributeNsSafe(
$rdfans
,
'longdesc'
),
{
'element'
=>
$current_element
,
'xml_base'
=>
$hrefsrc_base
}
);
if
(
defined
$longdesc
)
{
my
$E
= {
current
=>
$new_subject_elem
,
subject
=>
$current_element
,
predicate
=>
$current_element
,
object
=>
$current_element
,
graph
=>
$graph_elem
,
};
}
}
if
(
defined
$new_subject
and
$new_subject
ne
$parent_subject
|| !
%$list_mappings
)
{
$list_mappings
= {
'::meta'
=> {
id
=> Data::UUID->new->create_str,
owner
=>
$current_element
,
},
};
}
if
(
$current_object_resource
)
{
if
(
$current_element
->hasAttributeNsSafe(
$rdfans
,
'inlist'
)
and
$current_element
->hasAttributeNsSafe(
$rdfans
,
'rel'
))
{
foreach
my
$r
(
@REL
)
{
$list_mappings
->{
$r
} = []
unless
defined
$list_mappings
->{
$r
};
push
@{
$list_mappings
->{
$r
} }, [
resource
=>
$current_object_resource
];
$activity
++;
}
}
my
$E
= {
current
=>
$current_element
,
subject
=>
$new_subject_elem
,
predicate
=>
$current_element
,
object
=>
$current_object_resource_elem
,
graph
=>
$graph_elem
,
};
unless
(
$current_element
->hasAttributeNsSafe(
$rdfans
,
'inlist'
))
{
foreach
my
$r
(
@REL
)
{
$self
->_insert_triple_resource(
$E
,
$new_subject
,
$r
,
$current_object_resource
,
$graph
);
$activity
++;
}
}
$E
= {
current
=>
$current_element
,
subject
=>
$current_object_resource_elem
,
predicate
=>
$current_element
,
object
=>
$new_subject_elem
,
graph
=>
$graph_elem
,
};
foreach
my
$r
(
@REV
)
{
$self
->_insert_triple_resource(
$E
,
$current_object_resource
,
$r
,
$new_subject
,
$graph
);
$activity
++;
}
}
elsif
((
scalar
@REL
) || (
scalar
@REV
))
{
push
@$local_incomplete_triples
,
map
{
$current_element
->hasAttributeNsSafe(
$rdfans
,
'inlist'
)
?{
list
=>
do
{
$list_mappings
->{
$_
} = []
unless
defined
$list_mappings
->{
$_
};
$list_mappings
->{
$_
} },
direction
=>
'none'
,
}
:{
predicate
=>
$_
,
direction
=>
'forward'
,
graph
=>
$graph
,
predicate_element
=>
$current_element
,
graph_element
=>
$graph_elem
,
}
}
@REL
;
push
@$local_incomplete_triples
,
map
{
+{
predicate
=>
$_
,
direction
=>
'reverse'
,
graph
=>
$graph
,
predicate_element
=>
$current_element
,
graph_element
=>
$graph_elem
,
}
}
@REV
;
$current_object_resource
=
$self
->bnode;
$current_object_resource_elem
=
$current_element
;
}
my
@current_property_value
;
my
@prop
=
$self
->_split_tokens(
$current_element
->getAttributeNsSafe(
$rdfans
,
'property'
) );
my
$has_datatype
= 0;
my
$datatype
=
undef
;
if
(
$current_element
->hasAttributeNsSafe(
$rdfans
,
'datatype'
))
{
$has_datatype
= 1;
$datatype
=
$self
->_expand_curie(
$current_element
->getAttributeNsSafe(
$rdfans
,
'datatype'
),
element
=>
$current_element
,
attribute
=>
'datatype'
,
prefixes
=>
$local_uri_mappings
,
terms
=>
$local_term_mappings
,
xml_base
=>
$xml_base
,
);
}
if
(
@prop
)
{
if
(
$self
->{options}{datetime_attr}
and (
$current_element
->hasAttributeNsSafe(
$rdfans
,
'datetime'
)
&&
lc
(
$current_element
->tagName) eq
'time'
)) {
@current_property_value
= (
$current_element
->hasAttributeNsSafe(
$rdfans
,
'datetime'
)
?
$current_element
->getAttributeNsSafe(
$rdfans
,
'datetime'
)
:
$self
->_element_to_string(
$current_element
)
);
push
@current_property_value
,
do
{
local
$_
=
$current_property_value
[0];
if
(!!
$has_datatype
== !!1)
{
$datatype
}
elsif
(/^(\-?\d{4,})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(:(\d{2})(?:\.\d+)?)?(Z|(?:[\+\-]\d{2}:?\d{2}))?$/i)
elsif
(/^(\d{2}):(\d{2})(:(\d{2})(?:\.\d+)?)?(Z|(?:[\+\-]\d{2}:?\d{2}))?$/i)
elsif
(/^(\-?\d{4,})-(\d{2})-(\d{2})(Z|(?:[\+\-]\d{2}:?\d{2}))?$/i)
elsif
(/^(\-?\d{4,})-(\d{2})(Z|(?:[\+\-]\d{2}:?\d{2}))?$/i)
elsif
(/^(\-?\d{4,})(Z|(?:[\+\-]\d{2}:?\d{2}))?$/i)
elsif
(/^--(\d{2})-(\d{2})(Z|(?:[\+\-]\d{2}:?\d{2}))?$/i)
elsif
(/^---(\d{2})(Z|(?:[\+\-]\d{2}:?\d{2}))?$/i)
elsif
(/^--(\d{2})(Z|(?:[\+\-]\d{2}:?\d{2}))?$/i)
elsif
(/^P([\d\.]+Y)?([\d\.]+M)?([\d\.]+D)?(T([\d\.]+H)?([\d\.]+M)?([\d\.]+S)?)?$/i)
else
{
undef
}
},
$current_language
;
}
elsif
(
$self
->{options}{value_attr}
and
$current_element
->hasAttributeNsSafe(
$rdfans
,
'value'
))
{
@current_property_value
= (
$current_element
->getAttributeNsSafe(
$rdfans
,
'value'
),
(
$has_datatype
?
$datatype
:
undef
),
$current_language
,
);
}
elsif
(
$current_element
->hasAttributeNsSafe(
$rdfans
,
'content'
))
{
@current_property_value
= (
$current_element
->getAttributeNsSafe(
$rdfans
,
'content'
),
(
$has_datatype
?
$datatype
:
undef
),
$current_language
,
);
}
elsif
(
defined
$self
->{options}{bookmark_end}
and
defined
$self
->{options}{bookmark_name}
and
sprintf
(
'{%s}%s'
,
$current_element
->namespaceURI,
$current_element
->localname)
~~ [
'{}'
.
$self
->{options}{bookmark_start},
$self
->{options}{bookmark_start}]
) {
@current_property_value
= (
$self
->_element_to_bookmarked_string(
$current_element
),
(
$has_datatype
?
$datatype
:
undef
),
$current_language
,
);
}
elsif
(
$has_datatype
and
$datatype
eq
''
)
{
@current_property_value
= (
$self
->_element_to_string(
$current_element
),
(
$has_datatype
?
$datatype
:
undef
),
$current_language
,
);
}
elsif
(
$datatype
eq RDF_XMLLIT)
{
@current_property_value
= (
$self
->_element_to_xml(
$current_element
,
$current_language
),
RDF_XMLLIT,
$current_language
,
);
$recurse
=
$self
->{options}{xmllit_recurse};
}
elsif
(
$has_datatype
)
{
if
(
$current_element
->hasAttributeNsSafe(
$rdfans
,
'content'
))
{
@current_property_value
= (
$current_element
->getAttributeNsSafe(
$rdfans
,
'content'
),
$datatype
,
$current_language
,
);
}
else
{
@current_property_value
= (
$self
->_element_to_string(
$current_element
),
$datatype
,
$current_language
,
);
}
}
elsif
(
$self
->{options}{property_resources}
and !
$current_element
->hasAttributeNsSafe(
$rdfans
,
'datatype'
)
and !
$current_element
->hasAttributeNsSafe(
$rdfans
,
'content'
)
and !
$current_element
->hasAttributeNsSafe(
$rdfans
,
'rel'
)
and !
$current_element
->hasAttributeNsSafe(
$rdfans
,
'rev'
)
and (
$current_element
->hasAttributeNsSafe(
$rdfans
,
'resource'
)
or
$current_element
->hasAttributeNsSafe(
$rdfans
,
'href'
)
or
$current_element
->hasAttributeNsSafe(
$rdfans
,
'src'
)
&&
$self
->{options}{src_sets_object}
))
{
my
$resource
;
foreach
my
$attr
(
qw(resource href src)
)
{
next
unless
$current_element
->hasAttributeNsSafe(
$rdfans
,
$attr
);
$resource
=
$self
->_expand_curie(
$current_element
->getAttributeNsSafe(
$rdfans
,
$attr
),
element
=>
$current_element
,
attribute
=>
$attr
,
prefixes
=>
$local_uri_mappings
,
terms
=>
$local_term_mappings
,
xml_base
=>
$xml_base
,
);
last
if
defined
$resource
;
}
@current_property_value
= ([
$resource
])
if
defined
$resource
;
}
elsif
(
$self
->{options}{property_resources}
and
defined
$typed_resource
and
$current_element
->hasAttributeNsSafe(
$rdfans
,
'typeof'
)
and !
$current_element
->hasAttributeNsSafe(
$rdfans
,
'about'
))
{
@current_property_value
= ([
$typed_resource
]);
}
elsif
(not
$current_element
->getElementsByTagName(
'*'
))
{
@current_property_value
= (
$self
->_element_to_string(
$current_element
),
(
$has_datatype
?
$datatype
:
undef
),
$current_language
,
);
}
elsif
(!
$has_datatype
and
$current_element
->getElementsByTagName(
'*'
))
{
if
(
$self
->{options}{xmllit_default})
{
@current_property_value
= (
$self
->_element_to_xml(
$current_element
,
$current_language
),
RDF_XMLLIT,
$current_language
);
$recurse
=
$self
->{options}{xmllit_recurse};
}
else
{
@current_property_value
= (
$self
->_element_to_string(
$current_element
),
undef
,
$current_language
);
}
}
else
{
die
(
"How did we get here??\n"
);
}
}
my
$E
= {
current
=>
$current_element
,
subject
=>
$new_subject_elem
,
predicate
=>
$current_element
,
object
=>
$current_element
,
graph
=>
$graph_elem
,
};
foreach
my
$property
(
@prop
)
{
next
unless
defined
$current_property_value
[0];
my
$p
=
$self
->_expand_curie(
$property
,
element
=>
$current_element
,
attribute
=>
'property'
,
prefixes
=>
$local_uri_mappings
,
terms
=>
$local_term_mappings
,
xml_base
=>
$xml_base
,
);
next
unless
defined
$p
;
if
(
ref
$current_property_value
[0] eq
'ARRAY'
)
{
if
(
$current_element
->hasAttributeNsSafe(
$rdfans
,
'inlist'
))
{
$list_mappings
->{
$p
} = []
unless
defined
$list_mappings
->{
$p
};
push
@{
$list_mappings
->{
$p
} }, [
resource
=>
$current_property_value
[0][0]];
}
else
{
$self
->_insert_triple_resource(
$E
,
$new_subject
,
$p
,
$current_property_value
[0][0],
$graph
);
$activity
++;
}
}
else
{
if
(
$current_element
->hasAttributeNsSafe(
$rdfans
,
'inlist'
))
{
$list_mappings
->{
$p
} = []
unless
defined
$list_mappings
->{
$p
};
push
@{
$list_mappings
->{
$p
} }, [
literal
=>
@current_property_value
];
}
else
{
$self
->_insert_triple_literal(
$E
,
$new_subject
,
$p
,
@current_property_value
,
$graph
);
$activity
++;
}
}
}
if
(!
$skip_element
&&
defined
$new_subject
)
{
foreach
my
$it
(
@$incomplete_triples
)
{
my
$direction
=
$it
->{direction};
my
$predicate
=
$it
->{predicate};
my
$parent_graph
=
$it
->{graph};
if
(
$direction
eq
'none'
and
defined
$it
->{list})
{
push
@{
$it
->{list}}, [
resource
=>
$new_subject
];
}
elsif
(
$direction
eq
'forward'
)
{
my
$E
= {
current
=>
$current_element
,
subject
=>
$parent_subject_elem
,
predicate
=>
$it
->{predicate_element},
object
=>
$new_subject_elem
,
graph
=>
$it
->{graph_element},
};
$self
->_insert_triple_resource(
$E
,
$parent_subject
,
$predicate
,
$new_subject
,
$parent_graph
);
$activity
++;
}
elsif
(
$direction
eq
'reverse'
)
{
my
$E
= {
current
=>
$current_element
,
subject
=>
$new_subject_elem
,
predicate
=>
$it
->{predicate_element},
object
=>
$parent_subject_elem
,
graph
=>
$it
->{graph_element},
};
$self
->_insert_triple_resource(
$E
,
$new_subject
,
$predicate
,
$parent_subject
,
$parent_graph
);
$activity
++;
}
else
{
die
"Direction is '$direction'??"
;
}
}
}
my
$flag
= 0;
if
(
$recurse
)
{
my
$evaluation_context
;
if
(
$skip_element
)
{
$evaluation_context
= {
%$args
,
base
=>
$base
,
language
=>
$current_language
,
uri_mappings
=>
$uri_mappings
,
term_mappings
=>
$term_mappings
,
list_mappings
=>
$list_mappings
,
graph
=>
$graph
,
graph_elem
=>
$graph_elem
,
xml_base
=>
$xml_base
,
parent
=>
$args
,
};
}
else
{
$evaluation_context
= {
base
=>
$base
,
parent_subject
=>
$new_subject
,
parent_subject_elem
=>
$new_subject_elem
,
parent_object
=> (
defined
$current_object_resource
?
$current_object_resource
: (
defined
$new_subject
?
$new_subject
:
$parent_subject
)),
parent_object_elem
=> (
defined
$current_object_resource_elem
?
$current_object_resource_elem
: (
defined
$new_subject_elem
?
$new_subject_elem
:
$parent_subject_elem
)),
uri_mappings
=>
$local_uri_mappings
,
term_mappings
=>
$local_term_mappings
,
incomplete_triples
=>
$local_incomplete_triples
,
list_mappings
=>
$list_mappings
,
language
=>
$current_language
,
graph
=>
$graph
,
graph_elem
=>
$graph_elem
,
xml_base
=>
$xml_base
,
parent
=>
$args
,
};
}
foreach
my
$kid
(
$current_element
->getChildrenByTagName(
'*'
))
{
$flag
=
$self
->_consume_element(
$kid
,
$evaluation_context
) ||
$flag
;
}
}
if
(
$list_mappings
->{
'::meta'
}{owner} ==
$current_element
)
{
foreach
my
$iri
(
keys
%$list_mappings
)
{
next
if
$iri
eq
'::meta'
;
if
(
$args
->{list_mappings}{
$iri
} ==
$list_mappings
->{
$iri
}
and
ref
$args
->{list_mappings}{
$iri
} eq
'HASH'
and %{
$args
->{list_mappings}{
$iri
} })
{
next
;
}
my
@bnode
=
map
{
$self
->bnode; } @{
$list_mappings
->{
$iri
} };
my
$first
=
@bnode
?
$bnode
[0] :
undef
;
while
(
my
$bnode
=
shift
@bnode
)
{
my
$value
=
shift
@{
$list_mappings
->{
$iri
} };
my
$type
=
shift
@$value
;
my
$E
= {
current
=>
$current_element
,
graph
=>
$graph_elem
,
};
if
(
$type
eq
'literal'
)
{
$self
->_insert_triple_literal(
$E
,
$bnode
, RDF_FIRST,
@$value
,
$graph
);
}
else
{
$self
->_insert_triple_resource(
$E
,
$bnode
, RDF_FIRST,
@$value
,
$graph
);
}
if
(
exists
$bnode
[0])
{
$self
->_insert_triple_resource(
$E
,
$bnode
, RDF_REST,
$bnode
[0],
$graph
);
}
else
{
$self
->_insert_triple_resource(
$E
,
$bnode
, RDF_REST, RDF_NIL,
$graph
);
}
}
my
$E
= {
current
=>
$current_element
,
subject
=>
$new_subject_elem
,
predicate
=>
$current_element
,
graph
=>
$graph_elem
,
};
my
$attr
=
'REL'
;
if
(
defined
$first
)
{
$attr
eq
'REV'
?
$self
->_insert_triple_resource(
$E
,
$first
,
$iri
,
$new_subject
,
$graph
)
:
$self
->_insert_triple_resource(
$E
,
$new_subject
,
$iri
,
$first
,
$graph
);
}
else
{
$attr
eq
'REV'
?
$self
->_insert_triple_resource(
$E
, RDF_NIL,
$iri
,
$new_subject
,
$graph
)
:
$self
->_insert_triple_resource(
$E
,
$new_subject
,
$iri
, RDF_NIL,
$graph
);
}
$activity
++;
}
}
return
1
if
$activity
||
$new_subject
||
$flag
;
return
0;
}
sub
set_callbacks
{
my
$self
=
shift
;
if
(
'HASH'
eq
ref
$_
[0])
{
$self
->{
'sub'
} =
$_
[0];
$self
->{
'sub'
}->{
'pretriple_resource'
} = \
&_print0
if
lc
(
$self
->{
'sub'
}->{
'pretriple_resource'
}||
''
) eq
'print'
;
$self
->{
'sub'
}->{
'pretriple_literal'
} = \
&_print1
if
lc
(
$self
->{
'sub'
}->{
'pretriple_literal'
}||
''
) eq
'print'
;
}
else
{
die
"Unsupported set_callbacks call.\n"
;
}
return
$self
;
}
sub
_print0
{
my
$self
=
shift
;
my
$element
=
shift
;
my
$subject
=
shift
;
my
$pred
=
shift
;
my
$object
=
shift
;
my
$graph
=
shift
;
if
(
$graph
)
{
print
"# GRAPH $graph\n"
;
}
if
(
$element
)
{
printf
(
"# Triple on element %s.\n"
,
$element
->nodePath);
}
else
{
printf
(
"# Triple.\n"
);
}
printf
(
"%s %s %s .\n"
,
(
$subject
=~ /^_:/ ?
$subject
:
"<$subject>"
),
"<$pred>"
,
(
$object
=~ /^_:/ ?
$object
:
"<$object>"
));
return
;
}
sub
_print1
{
my
$self
=
shift
;
my
$element
=
shift
;
my
$subject
=
shift
;
my
$pred
=
shift
;
my
$object
=
shift
;
my
$dt
=
shift
;
my
$lang
=
shift
;
my
$graph
=
shift
;
$object
=~ s/\\/\\\\/g;
$object
=~ s/\n/\\n/g;
$object
=~ s/\r/\\r/g;
$object
=~ s/\t/\\t/g;
$object
=~ s/\"/\\\"/g;
if
(
$graph
)
{
print
"# GRAPH $graph\n"
;
}
if
(
$element
)
{
printf
(
"# Triple on element %s.\n"
,
$element
->nodePath);
}
else
{
printf
(
"# Triple.\n"
);
}
printf
(
"%s %s %s%s%s .\n"
,
(
$subject
=~ /^_:/ ?
$subject
:
"<$subject>"
),
"<$pred>"
,
"\"$object\""
,
(
length
$dt
?
"^^<$dt>"
:
''
),
((
length
$lang
&& !
length
$dt
) ?
"\@$lang"
:
''
)
);
return
;
}
sub
element_subjects
{
my
(
$self
) =
shift
;
$self
->consume;
$self
->{element_subjects} =
shift
if
@_
;
return
$self
->{element_subjects};
}
sub
_insert_triple_resource
{
my
$self
=
shift
;
my
$element
=
shift
;
my
$subject
=
shift
;
my
$predicate
=
shift
;
my
$object
=
shift
;
my
$graph
=
shift
;
my
$suppress_triple
= 0;
$suppress_triple
=
$self
->{
'sub'
}->{
'pretriple_resource'
}(
$self
,
ref
$element
?
$element
->{current} :
undef
,
$subject
,
$predicate
,
$object
,
$graph
,
)
if
defined
$self
->{
'sub'
}->{
'pretriple_resource'
};
return
if
$suppress_triple
;
my
$to
;
if
(
$object
=~ m/^_:(.*)/)
{
$to
= RDF::Trine::Node::Blank->new($1);
}
else
{
$to
= RDF::Trine::Node::Resource->new(
$object
);
}
return
$self
->_insert_triple_common(
$element
,
$subject
,
$predicate
,
$to
,
$graph
);
}
sub
_insert_triple_literal
{
my
$self
=
shift
;
my
$element
=
shift
;
my
$subject
=
shift
;
my
$predicate
=
shift
;
my
$object
=
shift
;
my
$datatype
=
shift
;
my
$language
=
shift
;
my
$graph
=
shift
;
my
$suppress_triple
= 0;
$suppress_triple
=
$self
->{
'sub'
}->{
'pretriple_literal'
}(
$self
,
ref
$element
?
$element
->{current} :
undef
,
$subject
,
$predicate
,
$object
,
$datatype
,
$language
,
$graph
,
)
if
defined
$self
->{
'sub'
}->{
'pretriple_literal'
};
return
if
$suppress_triple
;
my
$to
;
if
(
defined
$datatype
)
{
if
(
$datatype
eq RDF_XMLLIT)
{
if
(
$self
->{options}{use_rtnlx})
{
eval
{
$to
= RDF::Trine::Node::Literal::XML->new(
$element
->childNodes);
};
}
if
( $@ || !
defined
$to
)
{
my
$orig
=
$RDF::Trine::Node::Literal::USE_XMLLITERALS
;
$RDF::Trine::Node::Literal::USE_XMLLITERALS
= 0;
$to
= RDF::Trine::Node::Literal->new(
$object
,
undef
,
$datatype
);
$RDF::Trine::Node::Literal::USE_XMLLITERALS
=
$orig
;
}
}
else
{
$to
= RDF::Trine::Node::Literal->new(
$object
,
undef
,
$datatype
);
}
}
else
{
$to
= RDF::Trine::Node::Literal->new(
$object
,
$language
,
undef
);
}
$self
->_insert_triple_common(
$element
,
$subject
,
$predicate
,
$to
,
$graph
);
}
sub
_insert_triple_common
{
my
$self
=
shift
;
my
$element
=
shift
;
my
$subject
=
shift
;
my
$predicate
=
shift
;
my
$to
=
shift
;
my
$graph
=
shift
;
my
$tp
= RDF::Trine::Node::Resource->new(
$predicate
);
my
$ts
;
if
(
$subject
=~ m/^_:(.*)/)
{
$ts
= RDF::Trine::Node::Blank->new($1);
}
else
{
$ts
= RDF::Trine::Node::Resource->new(
$subject
);
}
my
$statement
;
if
(
$self
->{
'options'
}->{
'graph'
} &&
$graph
)
{
$self
->{Graphs}->{
$graph
}++;
my
$tg
;
if
(
$graph
=~ m/^_:(.*)/)
{
$tg
= RDF::Trine::Node::Blank->new($1);
}
else
{
$tg
= RDF::Trine::Node::Resource->new(
$graph
);
}
$statement
= RDF::Trine::Statement::Quad->new(
$ts
,
$tp
,
$to
,
$tg
);
}
else
{
$statement
= RDF::Trine::Statement->new(
$ts
,
$tp
,
$to
);
}
my
$suppress_triple
= 0;
$suppress_triple
=
$self
->{
'sub'
}->{
'ontriple'
}(
$self
,
$element
,
$statement
)
if
(
$self
->{
'sub'
}->{
'ontriple'
});
return
if
$suppress_triple
;
$self
->{model}->add_statement(
$statement
);
}
sub
_atom_magic
{
my
$self
=
shift
;
my
$element
=
shift
;
return
$self
->bnode(
$element
, 1);
}
sub
_split_tokens
{
my
(
$self
,
$string
) =
@_
;
$string
||=
''
;
$string
=~ s/(^\s+|\s+$)//g;
my
@return
=
split
/\s+/,
$string
;
return
@return
;
}
sub
_element_to_bookmarked_string
{
my
(
$self
,
$bookmark
) =
@_
;
my
@name_attribute
;
if
(
$self
->{
'options'
}->{
'bookmark_name'
} =~ /^\{(.*)\}(.+)$/)
{
@name_attribute
= $1 ? ($1, $2) : (
undef
, $2);
}
else
{
@name_attribute
= (
undef
,
$self
->{
'options'
}->{
'bookmark_name'
});
}
my
(
$endtag_namespace
,
$endtag_localname
);
if
(
$self
->{
'options'
}->{
'bookmark_end'
} =~ /^\{(.*)\}(.+)$/)
{
(
$endtag_namespace
,
$endtag_localname
) = $1 ? ($1, $2) : (
undef
, $2);
}
else
{
(
$endtag_namespace
,
$endtag_localname
) = (
undef
,
$self
->{
'options'
}->{
'bookmark_end'
});
}
my
$string
=
''
;
my
$current
=
$bookmark
;
while
(
$current
)
{
$current
=
$self
->_find_next_node(
$current
);
if
(
defined
$current
&&
$current
->nodeType == XML_TEXT_NODE)
{
$string
.=
$current
->getData;
}
if
(
defined
$current
&&
$current
->nodeType == XML_ELEMENT_NODE
&&
$current
->localname eq
$endtag_localname
&&
$current
->namespaceURI eq
$endtag_namespace
&&
$current
->getAttributeNsSafe(
@name_attribute
) eq
$bookmark
->getAttributeNsSafe(
@name_attribute
))
{
$current
=
undef
;
}
}
return
$string
;
}
sub
_find_next_node
{
my
(
$self
,
$node
) =
@_
;
if
(
$node
->nodeType == XML_ELEMENT_NODE)
{
my
@kids
=
$node
->childNodes;
return
$kids
[0]
if
@kids
;
}
my
$ancestor
=
$node
;
while
(
$ancestor
)
{
return
$ancestor
->nextSibling
if
$ancestor
->nextSibling;
$ancestor
=
$ancestor
->parentNode;
}
return
undef
;
}
sub
_element_to_string
{
my
$self
=
shift
;
my
$dom
=
shift
;
if
(
$dom
->nodeType == XML_TEXT_NODE)
{
return
$dom
->getData;
}
elsif
(
$dom
->nodeType == XML_ELEMENT_NODE)
{
my
$rv
=
''
;
foreach
my
$kid
(
$dom
->childNodes)
{
$rv
.=
$self
->_element_to_string(
$kid
); }
return
$rv
;
}
return
''
;
}
sub
_element_to_xml
{
my
$self
=
shift
;
my
$dom
=
shift
;
my
$lang
=
shift
;
my
$rv
;
foreach
my
$kid
(
$dom
->childNodes)
{
my
$fakelang
= 0;
if
((
$kid
->nodeType == XML_ELEMENT_NODE) &&
defined
$lang
)
{
unless
(
$kid
->hasAttributeNS(XML_XML_NS,
'lang'
))
{
$kid
->setAttributeNS(XML_XML_NS,
'lang'
,
$lang
);
$fakelang
++;
}
}
$rv
.=
$kid
->toStringEC14N(1);
if
(
$fakelang
)
{
$kid
->removeAttributeNS(XML_XML_NS,
'lang'
);
}
}
return
$rv
;
}
sub
bnode
{
my
$self
=
shift
;
my
$element
=
shift
;
my
$save_me
=
shift
|| 0;
my
$ident
=
shift
||
undef
;
if
(
defined
$element
and
$self
->{
'saved_bnodes'
}->{
$element
->nodePath })
{
return
$self
->{
'saved_bnodes'
}->{
$element
->nodePath };
}
elsif
(
defined
$ident
and
$self
->{
'saved_bnodes'
}->{
$ident
})
{
return
$self
->{
'saved_bnodes'
}->{
$ident
};
}
$self
->uri,
$self
->{element}->getAttribute(
'id'
))
if
(
$self
->{options}->{tdb_service} &&
$element
&&
length
$element
->getAttribute(
'id'
));
unless
(
defined
$self
->{bnode_prefix})
{
$self
->{bnode_prefix} = Data::UUID->new->create_str;
$self
->{bnode_prefix} =~ s/-//g;
}
my
$rv
;
if
(
$self
->{options}->{skolemize})
{
$rv
=
sprintf
(
'tag:buzzword.org.uk,2010:RDF-RDFa-Parser:skolem:%s:%04d'
,
$self
->{bnode_prefix},
$self
->{bnodes}++);
}
else
{
$rv
=
sprintf
(
'_:rdfa%snode%04d'
,
$self
->{bnode_prefix},
$self
->{bnodes}++);
}
if
(
$save_me
and
defined
$element
)
{
$self
->{
'saved_bnodes'
}->{
$element
->nodePath } =
$rv
;
}
if
(
defined
$ident
)
{
$self
->{
'saved_bnodes'
}->{
$ident
} =
$rv
;
}
return
$rv
;
}
sub
_valid_lang
{
my
(
$self
,
$value_to_test
) =
@_
;
return
1
if
(
defined
$value_to_test
) && (
$value_to_test
eq
''
);
return
0
unless
defined
$value_to_test
;
my
$alpha
=
'[a-z]'
;
my
$digit
=
'[0-9]'
;
my
$alphanum
=
'[a-z0-9]'
;
my
$x
=
'x'
;
my
$singleton
=
'[a-wyz]'
;
my
$s
=
'[_-]'
;
my
$language
=
'([a-z]{2,8}) | ([a-z]{2,3} $s [a-z]{3})'
;
my
$script
=
'[a-z]{4}'
;
my
$region
=
'(?: [a-z]{2}|[0-9]{3})'
;
my
$variant
=
'(?: [a-z0-9]{5,8} | [0-9] [a-z0-9]{3} )'
;
my
$extension
=
'(?: [a-wyz] (?: [_-] [a-z0-9]{2,8} )+ )'
;
my
$privateUse
=
'(?: x (?: [_-] [a-z0-9]{1,8} )+ )'
;
my
$grandfathered
= '(?:
(en [_-] GB [_-] oed)
| (i [_-] (?: ami | bnn |
default
| enochian | hak | klingon | lux | mingo | navajo | pwn | tao | tay | tsu ))
| (
no
[_-] (?: bok | nyn ))
| (sgn [_-] (?: BE [_-] (?: fr | nl) | CH [_-] de ))
| (zh [_-] min [_-] nan)
)';
my
$variantList
=
$variant
.
'(?:'
.
$s
.
$variant
.
')*'
;
my
$extensionList
=
$extension
.
'(?:'
.
$s
.
$extension
.
')*'
;
my
$langtag
= "
(
$language
)
(
$s
(
$script
) )?
(
$s
(
$region
) )?
(
$s
(
$variantList
) )?
(
$s
(
$extensionList
) )?
(
$s
(
$privateUse
) )?
";
my
$r
= (
$value_to_test
=~
/^(
(
$langtag
)
| (
$privateUse
)
| (
$grandfathered
)
)$/xi);
return
$r
;
}
sub
_expand_curie
{
my
(
$self
,
$token
,
%args
) =
@_
;
my
$r
=
$self
->__expand_curie(
$token
,
%args
);
if
(
defined
$self
->{
'sub'
}->{
'ontoken'
})
{
return
$self
->{
'sub'
}->{
'ontoken'
}(
$self
,
$args
{element},
$token
,
$r
);
}
return
$r
;
}
sub
__expand_curie
{
my
(
$self
,
$token
,
%args
) =
@_
;
{
my
$bnode
;
if
(
$token
eq
'_:'
||
$token
eq
'[_:]'
)
{
$bnode
=
$self
->bnode(
undef
,
undef
,
'_:'
); }
elsif
(
$token
=~ /^_:(.+)$/i ||
$token
=~ /^\[_:(.+)\]$/i)
{
$bnode
=
$self
->bnode(
undef
,
undef
,
'_:'
.$1); }
if
(
defined
$bnode
)
{
if
(
$args
{
'attribute'
} =~ /^(rel|rev|property|datatype)$/i)
{
$self
->_log_error(
ERR_ERROR,
ERR_CODE_BNODE_WRONGPLACE,
"Blank node found in $args{attribute} where URIs are expected as values."
,
token
=>
$token
,
element
=>
$args
{element},
attribute
=>
$args
{attribute},
);
return
$1
if
$token
=~ /^\[_:(.+)\]$/i;
return
$token
;
}
return
$bnode
;
}
}
my
$is_safe
= 0;
if
(
$token
=~ /^\[(.*)\]$/)
{
$is_safe
= 1;
$token
= $1;
}
if
(
$token
=~ /^(
$XML::RegExp::NCName
)$/
and (
$is_safe
||
$args
{
'attribute'
} =~ /^(rel|rev|property|typeof|datatype|role)$/i ||
$args
{
'allow_unsafe_default_vocab'
}))
{
my
$suffix
=
$token
;
if
(
$args
{
'attribute'
} eq
'role'
)
elsif
(
defined
$args
{
'prefixes'
}{
'(VOCAB)'
})
{
return
$args
{
'prefixes'
}{
'(VOCAB)'
} .
$suffix
; }
return
undef
if
$is_safe
;
}
if
(
$token
=~ /^(
$XML::RegExp::NCName
)$/
and (
$is_safe
||
$args
{
'attribute'
} =~ /^(rel|rev|property|typeof|datatype|role)$/i ||
$args
{
'allow_unsafe_term'
}))
{
my
$terms
=
$args
{
'terms'
};
my
$attr
=
$args
{
'attribute'
};
return
$terms
->{
'sensitive'
}{
$attr
}{
$token
}
if
defined
$terms
->{
'sensitive'
}{
$attr
}{
$token
};
return
$terms
->{
'sensitive'
}{
'*'
}{
$token
}
if
defined
$terms
->{
'sensitive'
}{
'*'
}{
$token
};
return
$terms
->{
'insensitive'
}{
$attr
}{
lc
$token
}
if
defined
$terms
->{
'insensitive'
}{
$attr
}{
lc
$token
};
return
$terms
->{
'insensitive'
}{
'*'
}{
lc
$token
}
if
defined
$terms
->{
'insensitive'
}{
'*'
}{
lc
$token
};
}
if
(
$token
=~ /^(
$XML::RegExp::NCName
)?:(\S*)$/
and (
$is_safe
or
$args
{attribute} =~ /^(rel|rev|property|typeof|datatype|role)$/i
or
$self
->{options}{safe_optional}
))
{
$token
=~ /^(
$XML::RegExp::NCName
)?:(\S*)$/;
my
$prefix
= (
defined
$1 &&
length
$1) ? $1 :
'(DEFAULT PREFIX)'
;
my
$suffix
= $2;
if
(
defined
$args
{
'prefixes'
}{
'(DEFAULT PREFIX)'
} &&
$prefix
eq
'(DEFAULT PREFIX)'
)
{
return
$args
{
'prefixes'
}{
'(DEFAULT PREFIX)'
} .
$suffix
; }
elsif
(
defined
$args
{
'prefixes'
}{
'sensitive'
}{
$prefix
})
{
return
$args
{
'prefixes'
}{
'sensitive'
}{
$prefix
} .
$suffix
; }
elsif
(
defined
$args
{
'prefixes'
}{
'insensitive'
}{
lc
$prefix
})
{
return
$args
{
'prefixes'
}{
'insensitive'
}{
lc
$prefix
} .
$suffix
; }
if
(
$is_safe
)
{
$prefix
= (
$prefix
eq
'(DEFAULT PREFIX)'
) ?
''
:
$prefix
;
$self
->_log_error(
ERR_WARNING,
ERR_CODE_CURIE_UNDEFINED,
"CURIE '$token' used in safe CURIE, but '$prefix' is undefined."
,
token
=>
$token
,
element
=>
$args
{element},
attribute
=>
$args
{attribute},
prefix
=>
$prefix
,
);
return
undef
;
}
}
if
(
$self
->{options}{prefix_bare}
and
$token
=~ /^(
$XML::RegExp::NCName
)$/
and (
$is_safe
or
$args
{attribute} =~ /^(rel|rev|property|typeof|datatype|role)$/i
or
$self
->{options}{safe_optional}
))
{
my
$prefix
=
$token
;
my
$suffix
=
''
;
if
(
defined
$args
{
'prefixes'
}{
'sensitive'
}{
$prefix
})
{
return
$args
{
'prefixes'
}{
'sensitive'
}{
$prefix
} .
$suffix
; }
elsif
(
defined
$args
{
'prefixes'
}{
'insensitive'
}{
lc
$prefix
})
{
return
$args
{
'prefixes'
}{
'insensitive'
}{
lc
$prefix
} .
$suffix
; }
}
if
(
$token
=~ /^[A-Z][A-Z0-9\.\+-]*:/i and !
$is_safe
and (
$self
->{
'options'
}{
'full_uris'
} ||
$args
{
'attribute'
} =~ /^(about|resource|graph)$/i))
{
return
$token
;
}
if
(!
$is_safe
and (
$args
{
'attribute'
} =~ /^(about|resource|graph)$/i ||
$args
{
'allow_relative'
}))
{
return
$self
->uri(
$token
, {
'element'
=>
$args
{
'element'
},
'xml_base'
=>
$args
{
'xml_base'
}});
}
$self
->_log_error(
ERR_WARNING,
ERR_CODE_CURIE_FELLTHROUGH,
"Couldn't make sense of token '$token'."
,
token
=>
$token
,
element
=>
$args
{element},
attribute
=>
$args
{attribute},
);
return
undef
;
}
__PACKAGE__