def get_creation_date_libxslt(ctx, recID, fmt="%Y-%m-%dT%H:%M:%SZ"): """ libxslt extension function: Bridge between BibFormat and XSL stylesheets. Returns record creation date. 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 """ try: if isinstance(recID, str): recID_int = int(recID) elif isinstance(recID, (int, long)): recID_int = recID else: recID_int = libxml2.xmlNode(_obj=recID[0]).children.content if isinstance(fmt, str): fmt_str = fmt else: fmt_str = libxml2.xmlNode(_obj=recID[0]).children.content return get_creation_date(recID_int, fmt_str) except Exception, err: sys.stderr.write("Error during formatting function evaluation: " + \ str(err) + \ '\n') return ''
def itemLink(self, ctx, baseURL, title, postID=""): """ Encodes special characters in URLs so that they can be used by the document function. """ if isinstance(title, list) and len(title) == 0: title = "" elif isinstance(title, list) and len(title) > 0: title = libxml2.xmlNode(_obj=title[0]).content if isinstance(baseURL, list): baseURL = libxml2.xmlNode(_obj=baseURL[0]).content # Handle escaping of real underscores title = replace(title, "_", "\_") title = replace(title, " ", "_") if isinstance(postID, list): postID = libxml2.xmlNode(_obj=postID[0]).content title = quote("_" + title) url = "%s/%s%s.item" % (baseURL, postID, title) return url
def updateRecord(self, ctx, sysConfig, entryID, entry): print "updating record" try: if (not isinstance(entryID, str)): node = libxml2.xmlNode(_obj=entryID[0]) entryID = node.content entry = libxml2.xmlNode(_obj=entry[0]) db = self._getDatabase(sysConfig) db.updateRecord(None, entryID, entry.serialize()) return "success" except: db.log.exception("DbXslExtension: Error updating") return "Error"
def bibconvert_function_libxslt(ctx, value, func): """ libxslt extension function: Bridge between BibConvert formatting functions and XSL stylesheets. Can be used in that way in XSL stylesheet (provided xmlns:fn="http://cdsweb.cern.ch/bibconvert/fn" has been declared): <xsl:value-of select="fn:format(., 'ADD(mypref,mysuff)')"/> (Adds strings 'mypref' and 'mysuff' as prefix/suffix to current node value, using BibConvert ADD function) if value is int, value is converted to string if value is Node (PyCObj), first child node (text node) is taken as value """ try: if isinstance(value, str): string_value = value elif isinstance(value, (int, long)): string_value = str(value) else: string_value = libxml2.xmlNode(_obj=value[0]).children.content return FormatField(string_value, func).rstrip('\n') except Exception, err: sys.stderr.write("Error during formatting function evaluation: " + \ str(err) + \ '\n')
def xpathQuery(self, ctx, sysConfig, xpath): # Get the database configuration try: db = self._getDatabase(sysConfig) if (not isinstance(xpath, str)): node = libxml2.xmlNode(_obj=xpath[0]) xpath = node.content content = db.xpathQuery(None, xpath) # See if this looks like an XML result if (content.startswith("<?xml")): doc = XMLFragment(content) # Extract the expected result set now that we've converted into libxml format. result = doc.xpathEval("/results/*") self.cleanupList.append(doc) else: doc = XMLFragment(libxml2.newDoc("1.0")) result = [doc.newDocText(content)] self.cleanupList.append(doc) return result except Exception, err: db.log.exception("DbXslExtension: Error searching")
def eval_bibformat_libxslt(ctx, recID, template_code): """ libxslt extension function: Bridge between BibFormat and XSL stylesheets. Returns the evaluation of the given piece of format template 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 '"' """ from invenio.bibformat_engine import \ format_with_format_template, \ BibFormatObject try: if isinstance(recID, str): recID_int = int(recID) elif isinstance(recID, (int, long)): recID_int = recID else: recID_int = libxml2.xmlNode(_obj=recID[0]).children.content bfo = BibFormatObject(recID_int) return format_with_format_template( None, bfo, verbose=0, format_template_code=template_code)[0] except Exception, err: sys.stderr.write("Error during formatting function evaluation: " + \ str(err) + \ '\n') return ''
def textileProcess(self, ctx, content): """ An XSL-T extension function to process textile formatting included in a post. Note: this doesn't work correctly if you want to also post process the result as XSL. content - a single element list containing an xmlNode containing the data to style """ try: node = libxml2.xmlNode(_obj=content[0]) parserContext = libxslt.xpathParserContext(_obj=ctx) xpathContext = parserContext.context() resultContext = xpathContext.transformContext() # If this is CDATA content we want textile to treat like a pre tag content = replace(node.serialize(), "<![CDATA[", "<pre>") content = replace(content, "]]>", "</pre>") source = textile.textile(content) source = replace(source, "<pre>", "") source = replace(source, "</pre>", "") return source except: sys.stderr.write("Textile processing error ") sys.stderr.write(source) return ""
def getItem(self, ctx, sysConfig, baseURL, id, index): try: db = self._getDatabase(sysConfig) if not isinstance(id, str): node = libxml2.xmlNode(_obj=id[0]) id = node.content if id != "": if index == 0: content = db.xpathQuery(None, "/item[@id > " + str(id) + "]") else: content = db.xpathQuery(None, "/item[@id < " + str(id) + "]") ids = libxml2.parseDoc(content).xpathEval("/results/item/@id") idList = [] for id in ids: idList.append(int(id.content)) if len(ids) > 0: idList.sort() previousID = idList[index] previous = XMLFragment(db.getRecord(None, previousID)) title = previous.getValue("/item/title") return self.itemLink(ctx, baseURL, title, previousID) else: return "" else: return "" except Exception, err: db.log.exception("DbXslExtension: Error getting previous item")
def event_datetime_from_airsync(ctx, node=None): parser_ctx, transform_ctx = xml2util.ExtractContexts(ctx) if node: node = libxml2.xmlNode(_obj=node[0]) else: node = transform_ctx.current() return tzutils.TextToDate(xml2util.GetNodeValue(node)).strftime(DATE_FORMAT_EVENT)
def serialize(self, ctx, content): if not isinstance(content, str): result = [] for item in content: node = libxml2.xmlNode(_obj=item) result.append(node.serialize()) return "".join(result) return content
def getRecord(self, ctx, sysConfig, entryID): print "getting record" try: if (not isinstance(entryID, str)): node = libxml2.xmlNode(_obj=entryID[0]) entryID = node.content db = self._getDatabase(sysConfig) return db.getRecord(None, entryID) except Exception, err: db.log.exception("DbXslExtension: Error getting record") return "Error"
def addRecord(self, ctx, sysConfig, entry): print "adding record" try: entry = libxml2.xmlNode(_obj=entry[0]) db = self._getDatabase(sysConfig) db.addRecord(None, entry.serialize()) print "added record " + entry.serialize() return "success" except: db.log.exception("DbXslExtension: Error adding") return "Error"
def normalizeURL(self, ctx, url): """ Strips a URL down to just the host name. """ if isinstance(url, list): node = libxml2.xmlNode(_obj=url[0]) url = node.content print url url = url.strip() url = replace(url, "http://", "") url = url.split("/")[0] return url
def deleteRecord(self, ctx, sysConfig, entryID): try: if (not isinstance(entryID, str)): node = libxml2.xmlNode(_obj=entryID[0]) entryID = node.content db = self._getDatabase(sysConfig) db.deleteRecord(None, entryID) return "success" except: db.log.exception("DbXslExtension: Error deleting") return "Error"
def QueryTypeId(self, tpid): """ Queries the DMI data structure for a specific DMI type. """ if self.restype == DMIXML_NODE: ret = libxml2.xmlNode(_obj=xmlapi( query_type='t', result_type=self.restype, typeid=tpid)) elif self.restype == DMIXML_DOC: ret = libxml2.xmlDoc(_obj=xmlapi( query_type='t', result_type=self.restype, typeid=tpid)) else: raise TypeError, "Invalid result type value" return ret
def QuerySection(self, sectname): """ Queries the DMI data structure for a given section name. A section can often contain several DMI type elements """ if self.restype == DMIXML_NODE: ret = libxml2.xmlNode(_obj=xmlapi( query_type='s', result_type=self.restype, section=sectname)) elif self.restype == DMIXML_DOC: ret = libxml2.xmlDoc(_obj=xmlapi( query_type='s', result_type=self.restype, section=sectname)) else: raise TypeError, "Invalid result type value" return ret
def QueryTypeId(self, tpid): """ Queries the DMI data structure for a specific DMI type. """ if self.restype == DMIXML_NODE: ret = libxml2.xmlNode( _obj = xmlapi(query_type='t', result_type=self.restype, typeid=tpid)) elif self.restype == DMIXML_DOC: ret = libxml2.xmlDoc( _obj = xmlapi(query_type='t', result_type=self.restype, typeid=tpid)) else: raise TypeError("Invalid result type value") return ret
def bibconvert_escape_libxslt(dummy_ctx, value): """ Bridge to libxslt to escape the provided value. """ try: if isinstance(value, str): string_value = value elif isinstance(value, (int, long)): string_value = str(value) else: string_value = libxml2.xmlNode(_obj=value[0]).serialize("utf8") return encode_for_xml(string_value) except Exception, err: sys.stderr.write("Error during formatting function evaluation: " + str(err) + "\n")
def QuerySection(self, sectname): """ Queries the DMI data structure for a given section name. A section can often contain several DMI type elements """ if self.restype == DMIXML_NODE: ret = libxml2.xmlNode( _obj = xmlapi(query_type='s', result_type=self.restype, section=sectname) ) elif self.restype == DMIXML_DOC: ret = libxml2.xmlDoc( _obj = xmlapi(query_type='s', result_type=self.restype, section=sectname) ) else: raise TypeError("Invalid result type value") return ret
def bibconvert_escape_libxslt(dummy_ctx, value): """ Bridge to libxslt to escape the provided value. """ try: if isinstance(value, str): string_value = value elif isinstance(value, (int, long)): string_value = str(value) else: string_value = libxml2.xmlNode(_obj=value[0]).serialize('utf8') return encode_for_xml(string_value) except Exception, err: sys.stderr.write("Error during formatting function evaluation: " + \ str(err) + \ '\n')
def summarize(self, ctx, content, wordCount=50): result = "" # If the content-type is XML then the tags have already been escaped. So # we need to switch them back. summary = content if len(content) != 0: # If we're not getting a string then it should be a node so we convert. if not isinstance(content, str): node = libxml2.xmlNode(_obj=content[0]) summary = node.content # Make the selected number of words available words = summary.split(None, int(wordCount) + 1) result = " ".join(words[0 : int(wordCount)]) if len(words) > wordCount: result += "..." return result
def eval_bibformat_libxslt(ctx, recID, template_code): """ libxslt extension function: Bridge between BibFormat and XSL stylesheets. Returns the evaluation of the given piece of format template 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 libxslt @param recID: record ID @param template_code: the code calling a BFE_ as it would be use in format template @return: the evalued call to a format template (usually a call to a format element) @rtype: string """ #' from invenio.bibformat_engine import \ format_with_format_template, \ BibFormatObject try: if isinstance(recID, str): recID_int = int(recID) elif isinstance(recID, (int, long)): recID_int = recID else: recID_int = libxml2.xmlNode(_obj=recID[0]).children.content bfo = BibFormatObject(recID_int) return format_with_format_template(None, bfo, verbose=0, format_template_code=template_code)[0] except Exception, err: sys.stderr.write("Error during formatting function evaluation: " + \ str(err) + \ '\n') return ''
def eval_bibformat_libxslt(ctx, recid, template_code): """ libxslt extension function: Bridge between BibFormat and XSL stylesheets. Returns the evaluation of the given piece of format template 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="absoluterecurl">')" /> 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 libxslt @param recid: record ID @param template_code: the code calling a BFE_ as it would be use in format template @return: the evalued call to a format template (usually a call to a format element) @rtype: string """ from invenio.bibformat import format_with_format_template from invenio.bibformat_engine import BibFormatObject try: if isinstance(recid, str): recid_int = int(recid) elif isinstance(recid, (int, long)): recid_int = recid else: recid_int = libxml2.xmlNode(_obj=recid[0]).children.content bfo = BibFormatObject(recid_int) return format_with_format_template(None, bfo, verbose=0, format_template_code=template_code) except Exception, err: sys.stderr.write("Error during formatting function evaluation: " + str(err) + '\n') return ''
def _getDatabase(self, sysConfig): # Get the database configuration config = libxml2.xmlNode(_obj=sysConfig[0]) return Framework().getSite(WeblogUtil.configValue(config, "/blog/id")).db
def instruction(self): """Get the instruction node in the stylesheet""" ret = libxsltmod.xsltTransformGetInstruction(self._o) if ret == None: return None return libxml2.xmlNode(_obj=ret)
def getConfig(self, ctx, name): if not isinstance(name, str): node = libxml2.xmlNode(_obj=name[0]) name = node.content return Framework().getSite(name).getConfig().getDocument().xpathEval("/node()")
def current(self): """Get the current() node of a transformation""" ret = libxsltmod.xsltTransformGetCurrent(self._o) if ret == None: return None return libxml2.xmlNode(_obj=ret)
def insertNode(self): """Get the insertion node in the output document""" ret = libxsltmod.xsltTransformGetInsertNode(self._o) if ret == None: return None return libxml2.xmlNode(_obj=ret)
def _stanza(self,_doc,_node): """Process complete stanza.""" doc=libxml2.xmlDoc(_doc) node=libxml2.xmlNode(_node) self.stanza(doc,node)
def getKeyCallback(keyInfoNode, keyInfoCtx): # Convert PyCObject object into xmlNode and KeyInfoCtx Objects node = libxml2.xmlNode(_obj=keyInfoNode) ctx = xmlsec.KeyInfoCtx(_obj=keyInfoCtx) return xmlsec.keysMngrGetKey(node, ctx)
def adjustColumnWidths(ctx, nodeset): # # Small check to verify the context is correcly accessed # try: pctxt = libxslt.xpathParserContext(_obj=ctx) ctxt = pctxt.context() tctxt = ctxt.transformContext() except: pass # Get the nominal table width varString = lookupVariable(tctxt, "nominal.table.width", None) if varString == None: nominalWidth = 6 * pixelsPerInch; else: nominalWidth = convertLength(varString); # Get the requested table width tableWidth = lookupVariable(tctxt, "table.width", "100%") foStylesheet = (tctxt.variableLookup("stylesheet.result.type", None) == "fo") relTotal = 0 relParts = [] absTotal = 0 absParts = [] colgroup = libxml2.xmlNode(_obj = nodeset[0]) # If this is an foStylesheet, we've been passed a list of fo:table-columns. # Otherwise we've been passed a colgroup that contains a list of cols. if foStylesheet: colChildren = colgroup else: colChildren = colgroup.children col = colChildren while col != None: if foStylesheet: width = col.prop("column-width") else: width = col.prop("width") if width == None: width = "1*" relPart = 0.0 absPart = 0.0 starPos = string.find(width, "*") if starPos >= 0: relPart, absPart = string.split(width, "*", 2) relPart = float(relPart) relTotal = relTotal + float(relPart) else: absPart = width pixels = convertLength(absPart) absTotal = absTotal + pixels relParts.append(relPart) absParts.append(pixels) col = col.next # Ok, now we have the relative widths and absolute widths in # two parallel arrays. # # - If there are no relative widths, output the absolute widths # - If there are no absolute widths, output the relative widths # - If there are a mixture of relative and absolute widths, # - If the table width is absolute, turn these all into absolute # widths. # - If the table width is relative, turn these all into absolute # widths in the nominalWidth and then turn them back into # percentages. widths = [] if relTotal == 0: for absPart in absParts: if foStylesheet: inches = absPart / pixelsPerInch widths.append("%4.2fin" % inches) else: widths.append("%d" % absPart) elif absTotal == 0: for relPart in relParts: rel = relPart / relTotal * 100 widths.append(rel) widths = correctRoundingError(widths) else: pixelWidth = nominalWidth if string.find(tableWidth, "%") < 0: pixelWidth = convertLength(tableWidth) if pixelWidth <= absTotal: print "Table is wider than table width" else: pixelWidth = pixelWidth - absTotal absTotal = 0 for count in range(len(relParts)): rel = relParts[count] / relTotal * pixelWidth relParts[count] = rel + absParts[count] absTotal = absTotal + rel + absParts[count] if string.find(tableWidth, "%") < 0: for count in range(len(relParts)): if foStylesheet: pixels = relParts[count] inches = pixels / pixelsPerInch widths.append("%4.2fin" % inches) else: widths.append(relParts[count]) else: for count in range(len(relParts)): rel = relParts[count] / absTotal * 100 widths.append(rel) widths = correctRoundingError(widths) # Danger, Will Robinson! In-place modification of the result tree! # Side-effect free? We don' need no steenkin' side-effect free! count = 0 col = colChildren while col != None: if foStylesheet: col.setProp("column-width", widths[count]) else: col.setProp("width", widths[count]) count = count+1 col = col.next return nodeset
def adjustColumnWidths(ctx, nodeset): # # Small check to verify the context is correcly accessed # try: pctxt = libxslt.xpathParserContext(_obj=ctx) ctxt = pctxt.context() tctxt = ctxt.transformContext() except: pass # Get the nominal table width varString = lookupVariable(tctxt, "nominal.table.width", None) if varString == None: nominalWidth = 6 * pixelsPerInch; else: nominalWidth = convertLength(varString); # Get the requested table width tableWidth = lookupVariable(tctxt, "table.width", "100%") foStylesheet = (tctxt.variableLookup("stylesheet.result.type", None) == "fo") relTotal = 0 relParts = [] absTotal = 0 absParts = [] colgroup = libxml2.xmlNode(_obj = nodeset[0]) # If this is an foStylesheet, we've been passed a list of fo:table-columns. # Otherwise we've been passed a colgroup that contains a list of cols. if foStylesheet: colChildren = colgroup else: colChildren = colgroup.children col = colChildren while col != None: if foStylesheet: width = col.prop("column-width") else: width = col.prop("width") if width == None: width = "1*" relPart = 0.0 absPart = 0.0 starPos = string.find(width, "*") if starPos >= 0: relPart, absPart = string.split(width, "*", 2) relPart = float(relPart) relTotal = relTotal + float(relPart) else: absPart = width pixels = convertLength(absPart) absTotal = absTotal + pixels relParts.append(relPart) absParts.append(pixels) col = col.__next__ # Ok, now we have the relative widths and absolute widths in # two parallel arrays. # # - If there are no relative widths, output the absolute widths # - If there are no absolute widths, output the relative widths # - If there are a mixture of relative and absolute widths, # - If the table width is absolute, turn these all into absolute # widths. # - If the table width is relative, turn these all into absolute # widths in the nominalWidth and then turn them back into # percentages. widths = [] if relTotal == 0: for absPart in absParts: if foStylesheet: inches = absPart / pixelsPerInch widths.append("%4.2fin" % inches) else: widths.append("%d" % absPart) elif absTotal == 0: for relPart in relParts: rel = relPart / relTotal * 100 widths.append(rel) widths = correctRoundingError(widths) else: pixelWidth = nominalWidth if string.find(tableWidth, "%") < 0: pixelWidth = convertLength(tableWidth) if pixelWidth <= absTotal: print("Table is wider than table width") else: pixelWidth = pixelWidth - absTotal absTotal = 0 for count in range(len(relParts)): rel = relParts[count] / relTotal * pixelWidth relParts[count] = rel + absParts[count] absTotal = absTotal + rel + absParts[count] if string.find(tableWidth, "%") < 0: for count in range(len(relParts)): if foStylesheet: pixels = relParts[count] inches = pixels / pixelsPerInch widths.append("%4.2fin" % inches) else: widths.append(relParts[count]) else: for count in range(len(relParts)): rel = relParts[count] / absTotal * 100 widths.append(rel) widths = correctRoundingError(widths) # Danger, Will Robinson! In-place modification of the result tree! # Side-effect free? We don' need no steenkin' side-effect free! count = 0 col = colChildren while col != None: if foStylesheet: col.setProp("column-width", widths[count]) else: col.setProp("width", widths[count]) count = count+1 col = col.__next__ return nodeset
def _stanza(self, _doc, _node): """Process complete stanza.""" doc = libxml2.xmlDoc(_doc) node = libxml2.xmlNode(_node) self.stanza(doc, node)