our
$VERSION
=
"0.47"
;
class UR::Object::View::Default::Xsl {
is
=>
'UR::Object::View::Default::Text'
,
has
=> [
output_format
=> {
value
=>
'html'
},
transform
=> {
is
=>
'Boolean'
,
value
=> 0 },
xsl_variables
=> {
is
=>
'Hash'
,
is_optional
=> 1 },
rest_variable
=> {
value
=>
'/rest'
,
is_deprecated
=> 1 },
desired_perspective
=> { },
xsl_path
=> {
is_optional
=> 1,
doc
=>
'web relative path starting with / where the xsl '
.
'is located when serving from a web service'
},
xsl_root
=> {
doc
=>
'absolute path where xsl files will be found, expected '
.
'format is $xsl_path/$output_format/$perspective/'
.
'$normalized_class_name.xsl'
},
]
};
our
@EXPORT_OK
=
qw(type_to_url url_to_type)
;
sub
_generate_content {
my
(
$self
,
%params
) =
@_
;
if
(!
$self
->desired_perspective) {
$self
->desired_perspective(
$self
->perspective);
}
unless
(
$self
->xsl_root && -e
$self
->xsl_root) {
die
'xsl_root does not exist:'
.
$self
->xsl_root;
}
my
$xml_view
=
$self
->_get_xml_view(
%params
);
my
$doc
=
$self
->_generate_xsl_doc(
$xml_view
);
if
(
$self
->transform) {
return
$self
->transform_xml(
$xml_view
,
$doc
);
}
else
{
return
$doc
->toString(1);
}
}
sub
_get_xml_view {
my
$self
=
shift
;
my
%params
=
@_
;
my
$xml_view
;
eval
{
$xml_view
= UR::Object::View->create(
subject_class_name
=>
$self
->subject_class_name,
perspective
=>
$self
->desired_perspective,
toolkit
=>
'xml'
,
%params
);
};
if
($@) {
$DB::single
= 1;
$xml_view
= UR::Object::View->create(
subject_class_name
=>
$self
->subject_class_name,
perspective
=>
$self
->perspective,
toolkit
=>
'xml'
,
%params
);
}
return
$xml_view
;
}
sub
_generate_xsl_doc {
my
$self
=
shift
;
my
$xml_view
=
shift
;
my
$output_format
=
$self
->output_format;
my
$xsl_path
=
$self
->xsl_root;
unless
(
$self
->transform) {
$xsl_path
=
$self
->xsl_path;
}
my
$perspective
=
$self
->desired_perspective;
my
@include_files
=
$self
->_resolve_xsl_template_files(
$xml_view
,
$output_format
,
$xsl_path
,
$perspective
);
my
$rootxsl
=
"/$output_format/$perspective/root.xsl"
;
if
(!-e
$xsl_path
.
$rootxsl
) {
$rootxsl
=
"/$output_format/default/root.xsl"
;
}
my
$commonxsl
=
"/$output_format/common.xsl"
;
if
(-e
$xsl_path
.
$commonxsl
) {
push
(
@include_files
,
$commonxsl
);
}
no
warnings;
my
$doc
= XML::LibXML::Document->new(
"1.0"
,
"ISO-8859-1"
);
my
$ss
=
$doc
->createElementNS(
$xslns
,
'stylesheet'
);
$ss
->setAttribute(
'version'
,
'1.0'
);
$doc
->setDocumentElement(
$ss
);
$ss
->setNamespace(
$xslns
,
'xsl'
, 1);
my
$time
=
time
.
"000"
;
my
$display_name
=
$self
->subject->__display_name__;
my
$label_name
=
$self
->subject->__label_name__;
my
$set_var
=
sub
{
my
$e
=
$doc
->createElementNS(
$xslns
,
'param'
);
$e
->setAttribute(
'name'
,
$_
[0]);
$e
->appendChild(
$doc
->createTextNode(
$_
[1] ) );
$ss
->appendChild(
$e
)
};
$set_var
->(
'currentPerspective'
,
$perspective
);
$set_var
->(
'currentToolkit'
,
$output_format
);
$set_var
->(
'displayName'
,
$display_name
);
$set_var
->(
'labelName'
,
$label_name
);
$set_var
->(
'currentTime'
,
$time
);
$set_var
->(
'username'
,
$ENV
{
'REMOTE_USER'
});
if
(
my
$id
=
$self
->subject->id) {
$set_var
->(
'objectId'
,
$id
);
}
if
(
my
$class_name
=
$self
->subject->class) {
$set_var
->(
'objectClassName'
,
$class_name
);
}
if
(
my
$vars
=
$self
->xsl_variables) {
while
(
my
(
$key
,
$val
) =
each
%$vars
) {
$set_var
->(
$key
,
$val
);
}
}
else
{
$set_var
->(
'rest'
,
$self
->rest_variable);
}
my
$rootn
=
$doc
->createElementNS(
$xslns
,
'include'
);
$rootn
->setAttribute(
'href'
,
"$xsl_path$rootxsl"
);
$ss
->appendChild(
$rootn
);
for
(
@include_files
) {
my
$e
=
$doc
->createElementNS(
$xslns
,
'include'
);
$e
->setAttribute(
'href'
,
"$xsl_path$_"
);
$ss
->appendChild(
$e
)
}
return
$doc
;
}
sub
_resolve_xsl_template_files {
my
(
$self
,
$xml_view
,
$output_format
,
$xsl_path
,
$perspective
) =
@_
;
return
$xml_view
->xsl_template_files(
$output_format
,
$xsl_path
,
$perspective
,
);
}
sub
transform_xml {
my
(
$self
,
$xml_view
,
$style_doc
) =
@_
;
$xml_view
->subject(
$self
->subject);
my
$xml_content
=
$xml_view
->_generate_content();
$xml_content
=~ s/[^\x09\x0A\x0D\x20-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}]//go;
my
$parser
= XML::LibXML->new;
my
$xslt
= XML::LibXSLT->new;
my
$source
;
if
(
$xml_view
->can(
'_xml_doc'
) and
$xml_view
->_xml_doc) {
$source
=
$xml_view
->_xml_doc;
}
else
{
$source
=
$parser
->parse_string(
$xml_content
);
}
my
$stylesheet
=
$xslt
->parse_stylesheet(
$style_doc
);
my
$results
=
$stylesheet
->transform(
$source
);
my
$content
=
$stylesheet
->output_string(
$results
);
return
$content
;
}
sub
type_to_url {
join
(
'/'
,
map
{
s/(?<!^)([[:upper:]]{1})/-$1/g;
lc
;
}
split
(
'::'
,
$_
[0] )
);
}
sub
url_to_type {
join
(
'::'
,
map
{
$_
=
ucfirst
;
s/-(\w{1})/\u$1/g;
$_
;
}
split
(
'/'
,
$_
[0] )
);
}
XML::LibXSLT->register_function(
'urn:rest'
,
'typetourl'
, \
&type_to_url
);
XML::LibXSLT->register_function(
'urn:rest'
,
'urltotype'
, \
&url_to_type
);
1;