Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F86601491
xslt.py
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Mon, Oct 7, 11:57
Size
9 KB
Mime Type
text/x-python
Expires
Wed, Oct 9, 11:57 (1 d, 23 h)
Engine
blob
Format
Raw Data
Handle
21455403
Attached To
R3600 invenio-infoscience
xslt.py
View Options
# -*- coding: utf-8 -*-
##
## This file is part of Invenio.
## Copyright (C) 2007, 2008, 2009, 2010, 2011, 2014 CERN.
##
## Invenio is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License as
## published by the Free Software Foundation; either version 2 of the
## License, or (at your option) any later version.
##
## Invenio is distributed in the hope that it will be useful, but
## WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
## General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with Invenio; if not, write to the Free Software Foundation, Inc.,
## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
"""
bibformat_xslt_engine - Wrapper for an XSLT engine.
Some functions are registered in order to be used in XSL code:
- creation_date(recID)
- modification_date(recID)
Used by: bibformat_engine.py
"""
from
__future__
import
print_function
import
os
import
sys
from
lxml
import
etree
from
invenio.modules.formatter.config
import
CFG_BIBFORMAT_TEMPLATES_PATH
from
invenio.modules.formatter.api
import
(
get_creation_date
,
get_modification_date
)
CFG_BIBFORMAT_FUNCTION_NS
=
"http://cdsweb.cern.ch/bibformat/fn"
"""The namespace used for BibFormat function."""
def
_get_creation_date
(
ctx
,
recID
,
fmt
=
"%Y-%m-
%d
T%H:%M:%SZ"
):
"""
Bridge between BibFormat and XSL stylesheets.
Can be used in that way in XSL stylesheet (provided
``xmlns:fn="http://cdsweb.cern.ch/bibformat/fn"`` has been declared):
``<xsl:value-of select="fn:creation_date(445)"/>`` where 445 is a recID
if recID is string, value is converted to int
if recID is Node, first child node (text node) is taken as value
:param ctx: context as passed by lxml
:param recID: record ID
:param fmt: format of the returned date
:return: creation date of X{recID}
:rtype: str
"""
try
:
if
isinstance
(
recID
,
str
):
recID_int
=
int
(
recID
)
elif
isinstance
(
recID
,
(
int
,
long
)):
recID_int
=
recID
elif
isinstance
(
recID
,
list
):
recID
=
recID
[
0
]
if
isinstance
(
recID
,
str
):
recID_int
=
int
(
recID
)
else
:
recID_int
=
int
(
recID
.
text
)
else
:
recID_int
=
int
(
recID
.
text
)
if
isinstance
(
fmt
,
str
):
fmt_str
=
fmt
elif
isinstance
(
fmt
,
list
):
fmt
=
fmt
[
0
]
if
isinstance
(
fmt
,
str
):
fmt_str
=
fmt
else
:
fmt_str
=
fmt
.
text
else
:
fmt_str
=
fmt
.
text
return
get_creation_date
(
recID_int
,
fmt_str
)
except
Exception
as
err
:
print
(
"Error during formatting function evaluation: {0}"
.
format
(
err
),
file
=
sys
.
stderr
)
return
''
def
_get_modification_date
(
ctx
,
recID
,
fmt
=
"%Y-%m-
%d
T%H:%M:%SZ"
):
"""
Bridge between BibFormat and XSL stylesheets.
Can be used in that way in XSL stylesheet (provided
``xmlns:fn="http://cdsweb.cern.ch/bibformat/fn"`` has been declared):
``<xsl:value-of select="fn:modification_date(445)"/>`` where 445 is a
recID
if recID is string, value is converted to int
if recID is Node, first child node (text node) is taken as value
:param ctx: context as passed by lxml
:param recID: record ID
:param fmt: format of the returned date
:return: modification date of X{recID}
:rtype: str
"""
try
:
if
isinstance
(
recID
,
str
):
recID_int
=
int
(
recID
)
elif
isinstance
(
recID
,
(
int
,
long
)):
recID_int
=
recID
elif
isinstance
(
recID
,
list
):
recID
=
recID
[
0
]
if
isinstance
(
recID
,
str
):
recID_int
=
int
(
recID
)
else
:
recID_int
=
int
(
recID
.
text
)
else
:
recID_int
=
int
(
recID
.
text
)
if
isinstance
(
fmt
,
str
):
fmt_str
=
fmt
elif
isinstance
(
fmt
,
list
):
fmt
=
fmt
[
0
]
if
isinstance
(
fmt
,
str
):
fmt_str
=
fmt
else
:
fmt_str
=
fmt
.
text
else
:
fmt_str
=
fmt
.
text
return
get_modification_date
(
recID_int
,
fmt_str
)
except
Exception
as
err
:
print
(
"Error during formatting function evaluation: {0}"
.
format
(
err
),
file
=
sys
.
stderr
)
return
''
def
_eval_bibformat
(
ctx
,
recID
,
template_code
):
"""
Bridge between BibFormat and XSL stylesheets.
Can be used in that way in XSL stylesheet (provided
``xmlns:fn="http://cdsweb.cern.ch/bibformat/fn"`` has been declared)::
<xsl:value-of select="fn:eval_bibformat(marc:controlfield[@tag='001'],
'<BFE_SERVER_INFO var="recurl">')"/>
if recID is string, value is converted to int
if recID is Node, first child node (text node) is taken as value
template_code is evaluated as a format template piece of code. '<'
and '"' need to be escaped with '<' and '"'
:param ctx: context as passed by lxml
:param recID: record ID
:param template_code: the code calling a BFE_ as it would be used in
format template
:return: the evaluated call to a format template (usually a call to a
format element)
:rtype: str
"""
from
invenio.modules.formatter.engine
import
format_with_format_template
,
\
BibFormatObject
try
:
if
isinstance
(
recID
,
str
):
recID_int
=
int
(
recID
)
elif
isinstance
(
recID
,
(
int
,
long
)):
recID_int
=
recID
elif
isinstance
(
recID
,
list
):
recID
=
recID
[
0
]
if
isinstance
(
recID
,
str
):
recID_int
=
int
(
recID
)
else
:
recID_int
=
int
(
recID
.
text
)
else
:
recID_int
=
int
(
recID
.
text
)
bfo
=
BibFormatObject
(
recID_int
)
out
=
format_with_format_template
(
None
,
bfo
,
verbose
=
0
,
format_template_code
=
template_code
)
return
out
[
0
]
except
Exception
as
err
:
print
(
"Error during formatting function evaluation: {0}"
.
format
(
err
),
file
=
sys
.
stderr
)
return
''
def
format
(
xmltext
,
template_filename
=
None
,
template_source
=
None
):
"""
Process an XML text according to a template, and returns the result.
The template can be given either by name (or by path) or by source.
If source is given, name is ignored.
bibformat_xslt_engine will look for template_filename in standard
directories for templates. If not found, template_filename will be assumed
to be a path to a template. If none can be found, return None.
:param xmltext: The string representation of the XML to process
:param template_filename: The name of the template to use for the
processing
:param template_source: The configuration describing the processing.
:return: the transformed XML text.
"""
# Retrieve template and read it
if
template_source
:
template
=
template_source
elif
template_filename
:
try
:
path_to_templates
=
(
CFG_BIBFORMAT_TEMPLATES_PATH
+
os
.
sep
+
template_filename
)
if
os
.
path
.
exists
(
path_to_templates
):
template
=
file
(
path_to_templates
)
.
read
()
elif
os
.
path
.
exists
(
template_filename
):
template
=
file
(
template_filename
)
.
read
()
else
:
print
(
'{0} does not exist'
.
format
(
template_filename
),
file
=
sys
.
stderr
)
return
None
except
IOError
:
print
(
'{0} could not be read.'
.
format
(
template_filename
),
file
=
sys
.
stderr
)
return
None
else
:
print
(
'No templates were given.'
,
file
=
sys
.
stderr
)
return
None
# Some massaging of the input to avoid the default namespace issue
# in XPath. More elegant solution might be found though.
xmltext
=
xmltext
.
replace
(
'xmlns="http://www.loc.gov/MARC21/slim"'
,
''
)
# For older MARCXML records stored in bibfmt with empty indicators
xmltext
=
xmltext
.
replace
(
'ind1=""'
,
'ind1=" "'
)
xmltext
=
xmltext
.
replace
(
'ind2=""'
,
'ind2=" "'
)
result
=
""
try
:
xml
=
etree
.
XML
(
xmltext
)
except
etree
.
XMLSyntaxError
as
e
:
error
=
'The XML code given is invalid. [
%s
]'
%
(
e
,)
print
(
error
,
file
=
sys
.
stderr
)
return
result
except
:
error
=
'Failed to process the XML code.'
print
(
error
,
file
=
sys
.
stderr
)
return
result
try
:
xsl
=
etree
.
XML
(
template
)
except
etree
.
XMLSyntaxError
as
e
:
error
=
'The XSL code given is invalid. [
%s
]'
%
(
e
,)
print
(
error
,
file
=
sys
.
stderr
)
return
result
except
:
error
=
'Failed to process the XSL code.'
print
(
error
,
file
=
sys
.
stderr
)
return
result
try
:
fns
=
etree
.
FunctionNamespace
(
CFG_BIBFORMAT_FUNCTION_NS
)
fns
[
"creation_date"
]
=
_get_creation_date
fns
[
"modification_date"
]
=
_get_modification_date
fns
[
"eval_bibformat"
]
=
_eval_bibformat
except
etree
.
NamespaceRegistryError
as
e
:
error
=
'Failed registering the XPath extension function. [
%s
]'
%
e
print
(
error
,
file
=
sys
.
stderr
)
return
result
try
:
xslt
=
etree
.
XSLT
(
xsl
)
except
etree
.
XSLTParseError
as
e
:
error
=
'The XSL code given is invalid. [
%s
]'
%
e
print
(
error
,
file
=
sys
.
stderr
)
return
result
except
:
error
=
'Failed to process the XSL code.'
print
(
error
,
file
=
sys
.
stderr
)
return
result
try
:
temporary_result
=
xslt
(
xml
)
except
:
error
=
'Failed to perform the XSL transformation.'
print
(
error
,
file
=
sys
.
stderr
)
return
result
result
=
str
(
temporary_result
)
# Housekeeping
del
temporary_result
del
xslt
del
xsl
del
xml
return
result
Event Timeline
Log In to Comment