BuiltInExtFunctions.py :  » XML » 4Suite » 4Suite-XML-1.0.2 » Ft » Xml » Xslt » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » XML » 4Suite 
4Suite » 4Suite XML 1.0.2 » Ft » Xml » Xslt » BuiltInExtFunctions.py
########################################################################
# $Header: /var/local/cvsroot/4Suite/Ft/Xml/Xslt/BuiltInExtFunctions.py,v 1.30 2005/03/18 23:47:19 jkloth Exp $
"""
4XSLT specific extension functions (i.e. ones that create a node set)

Copyright 2005 Fourthought, Inc. (USA).
Detailed license and copyright information: http://4suite.org/COPYRIGHT
Project home, documentation, distributions: http://4suite.org/
"""
# Use this module only for functions that generate new node sets
# or for whatever reason need a processor object (e.g. FtKey needs
# a processor to read the key defs). Place others in
# Ft.Xml.XPath.BuiltInExtFunctions.py

import re

from Ft.Xml.Lib.XmlString import SplitQName
from Ft.Xml.XPath import FT_EXT_NAMESPACE
from Ft.Xml.XPath import Conversions
from Ft.Xml.Xslt import XsltRuntimeException,Error
from Ft.Xml.Xslt.XsltFunctions import Key

__all__ = ['ExtNamespaces', 'ExtFunctions',
           'FtKey',
           'Lookup',
           'Map',
           'DocAsString',
           'SearchRe',
           'SerializeXml',
           'Split',]


def FtKey(context, qname, keyList, realContextNode=None):
    """
    Query an XSLT key, but allow the user to override the context node for
    purposes of determining which source document to check.
    realContextNode is a node set from which the first node is extracted
    And used as the context node
    """
    if realContextNode:
        orig_node = context.node
        context.node = realContextNode[0]
        result = Key(context, qname, keyList)
        context.node = orig_node
    else:
        result = Key(context, qname, keyList)
    return result


def SearchRe(context, pattern, arg=None):
    """Do a regular expression search against the argument (i.e. get all matches)"""
    if not arg:
        arg = context.node
    arg = Conversions.StringValue(arg)
    matches_nodeset = []
    compiled = re.compile(pattern)

    processor = context.processor
    processor.pushResultTree(context.currentInstruction.baseUri)
    try:
        match = compiled.search(arg)
        while match:
            processor.writers[-1].startElement('Match')
            # .groups() return empty tuple when the pattern did not do grouping
            groups = match.groups() or (match.group(),)
            for group in groups:
                processor.writers[-1].startElement('Group')
                group and processor.writers[-1].text(group)
                processor.writers[-1].endElement('Group')
            processor.writers[-1].endElement('Match')
            match = compiled.search(arg, match.end())
    finally:
        rtf = processor.popResult()
    return rtf.childNodes


def Map(context, funcname, *nodesets):
    """
    Apply the function serially over the given node sets.
    In iteration i, the function is passed N parameters
    where N is the number of argument node sets.  Each
    parameter is a node set of size 1, whose node is
    the ith node of the corresponding argument node set.
    The return value is a node set consisting of a series
    of result-tree nodes, each of which is a text node
    whose value is the string value of the result of the
    ith function invocation.
    Warning: this function uses the implied ordering of the node set
    Based on its implementation as a Python list.  But in reality
    There is no reliable ordering of XPath node sets.
    Therefore this function is not recommended for use with
    more than one node set parameter.
    """
    (prefix, local) = SplitQName(funcname)
    uri = context.processorNss.get(prefix)
    if prefix and not uri:
        raise XsltRuntimeException(Error.UNDEFINED_PREFIX,
                                   context.currentInstruction, prefix)
    expanded = (prefix and uri or '', local)
    func = context.functions.get(expanded)
    if not func:
        raise Exception('Dynamically invoked function %s not found.'%funcname)

    flist = [func]*len(nodesets)
    lf = lambda x, f, *args: apply(f, args)
    retlist = apply(map, (lf, flist) + nodesets)

    processor = context.processor
    processor.pushResultTree(context.currentInstruction.baseUri)
    try:
        for ret in retlist:
            processor.writers[-1].text(Conversions.StringValue(ret))
    finally:
        rtf = processor.popResult()
    return rtf.childNodes


def Lookup(context, name, key):
    """
    f:lookup() queries an index as defined by f:create-index.
    """
    name = Conversions.StringValue(name)
    key = Conversions.StringValue(key)
    processor = context.processor
    indices = processor.extensionParams.get((FT_EXT_NAMESPACE, 'indices'), {})
    index = indices.get(name, {})
    value = index.get(key, [])
    return value


def DocAsString(context, obj, encoding='UTF-8'):
    """
    Retrieves a document, similar to the document() function, but
    returns the document as an XPath string object rather than as a
    node-set.

    Security note: if the associated URI resolver allows file: URLs,
    this extension could be used to read arbitrary system files
    """
    sheet = context.processor.stylesheet
    baseUri = context.currentInstruction.baseUri

    if isinstance(obj, list):
        result = u''
        for node in obj:
            result += DocAsString(context,
                                  Conversions.StringValue(node),
                                  encoding)
    else:
        if hasattr(context, 'processor'):
            #In Xslt, use the ISF on the processor to resolve the URI
            isrc = context.processor.inputSourceFactory.fromUri(baseUri)
            isrc = isrc.resolve(Conversions.StringValue(obj),
                                hint="XSLT DOCUMENT FUNCTION")
            data = isrc.read()
            isrc.close()
            return data
        else:
            # the current instruction's base URI should suffice
            uri = Uri.BASIC_RESOLVER.normalize(
                Conversions.StringValue(obj),
                baseUri)
        if obj == u'' and baseUri in sheet.root.sources:
            result = sheet.root.sources[baseUri]
        else:
            resultfile = codecs.open(uri, 'rb', encoding)
            result = resultfile.read()
            resultfile.close()

    return result


def SerializeXml(context, nodeset, method=None,
                 omitxmldecl=1):
    """
    f:serialize-xml() takes a node set and turns it into a string
    representing the serialization of the node set, obtained
    by concatenating the serialization of each node in the
    node set in document order.

    See also: XPath (not XSLT) extension function f:parse-xml()
    """
    from Exslt.Common import NodeSet
    import cStringIO
    from Ft.Xml import EMPTY_NAMESPACE
    from Ft.Xml.Xslt.CopyOfElement import CopyNode
    nodeset = _NodeSet(context, nodeset)
    result = cStringIO.StringIO()
    processor = context.processor
    op = processor.outputParams.clone()
    method = method or (EMPTY_NAMESPACE, 'xml')
    op.method = method
    op.omitXmlDeclaration = omitxmldecl and "yes" or "no"
    processor.addHandler(op, result)

    for node in nodeset:
        CopyNode(processor, node)
    processor.removeHandler()
    return unicode(result.getvalue(), op.encoding)


def Split(context, arg, delim=u' '):
    """
    DEPRECATED.
    Equivalent to EXSLT's str:split().
    Splits a string according to a sub-string and return a node set
    of elements nodes, each of which is named "Split" and contains the
    split text
    For example f:split('A,B,C,') returns a node set of "Split" nodes
    having text nodes with values "A", "B" and "C"
    arg - converted to a string, is the string to split up
    delim - the delimiter upon which to split, defaults to " "
    """
    arg = Conversions.StringValue(arg)
    delim = Conversions.StringValue(delim)
    context.processor.pushResultTree(context.currentInstruction.baseUri)
    try:
        for text in arg.split(delim):
            context.processor.writers[-1].startElement('Split')
            context.processor.writers[-1].text(text)
            context.processor.writers[-1].endElement('Split')
    finally:
        rtf = context.processor.popResult()
    return rtf.childNodes



ExtNamespaces = {
    FT_EXT_NAMESPACE : 'f',
    }

ExtFunctions = {
    (FT_EXT_NAMESPACE, 'key') : FtKey,
    (FT_EXT_NAMESPACE, 'lookup') : Lookup,
    (FT_EXT_NAMESPACE, 'search-re') : SearchRe,
    (FT_EXT_NAMESPACE, 'map') : Map,
    (FT_EXT_NAMESPACE, 'doc-as-string'): DocAsString,
    (FT_EXT_NAMESPACE, 'serialize-xml') : SerializeXml,
    (FT_EXT_NAMESPACE, 'split'): Split,
    }

www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.