예제 #1
0
def SubstringBefore(context, outer, inner):
    """Function: <string> substring-before(<string>, <string>)"""
    outer = Conversions.StringValue(outer)
    inner = Conversions.StringValue(inner)
    index = string.find(outer, inner)
    if index == -1:
        return ''
    return outer[:index]
예제 #2
0
def SubstringAfter(context, outer, inner):
    """Function: <string> substring-after(<string>, <string>)"""
    outer = Conversions.StringValue(outer)
    inner = Conversions.StringValue(inner)
    index = string.find(outer, inner)
    if index == -1:
        return ''
    return outer[index + len(inner):]
예제 #3
0
def Replace(context, old, new, arg=None):
    """Do a global search and replace of the string contents"""
    if not arg:
        arg = context.node
    arg = Conversions.StringValue(arg)
    old = Conversions.StringValue(old)
    new = Conversions.StringValue(new)
    return string.replace(arg, old, new)
예제 #4
0
def Contains(context, outer, inner):
    """Function: <string> contains(<string>, <string>)"""
    outer = Conversions.StringValue(outer)
    inner = Conversions.StringValue(inner)
    if len(inner) == 1:
        return inner in outer and boolean.true or boolean.false
    else:
        return string.find(outer,
                           inner) != -1 and boolean.true or boolean.false
예제 #5
0
    def evaluate(self, context):
        if self._op == '=':
            true = boolean.true
            false = boolean.false
        else:
            true = boolean.false
            false = boolean.true

        lrt = self._left.evaluate(context)
        rrt = self._right.evaluate(context)
        lType = type(lrt)
        rType = type(rrt)
        if lType == types.ListType == rType:
            #Node set to node set
            for right_curr in rrt:
                right_curr = Conversions.StringValue(right_curr)
                for left_curr in lrt:
                    if right_curr == Conversions.StringValue(left_curr):
                        return true
            return false
        elif lType == types.ListType or rType == types.ListType:
            func = None
            if lType == types.ListType:
                set = lrt
                val = rrt
            else:
                set = rrt
                val = lrt
            if type(val) in NumberTypes:
                func = Conversions.NumberValue
            elif boolean.IsBooleanType(val):
                func = Conversions.BooleanValue
            elif type(val) == types.StringType:
                func = Conversions.StringValue
            else:
                #Deal with e.g. RTFs
                val = Conversions.StringValue(val)
                func = Conversions.StringValue
            for n in set:
                if func(n) == val:
                    return true
            return false

        if boolean.IsBooleanType(lrt) or boolean.IsBooleanType(rrt):
            rt = Conversions.BooleanValue(lrt) == Conversions.BooleanValue(rrt)
        elif lType in NumberTypes or rType in NumberTypes:
            rt = Conversions.NumberValue(lrt) == Conversions.NumberValue(rrt)
        else:
            rt = Conversions.StringValue(lrt) == Conversions.StringValue(rrt)
        if rt:
            # Due to the swapping of true/false, true might evaluate to 0
            # We cannot compact this to 'rt and true or false'
            return true
        return false
예제 #6
0
def Translate(context, source, fromChars, toChars):
    """Function: <string> translate(<string>, <string>, <string>)"""
    source = Conversions.StringValue(source)
    fromChars = Conversions.StringValue(fromChars)
    toChars = Conversions.StringValue(toChars)

    # string.maketrans/translate do not handle unicode
    translate = {}
    for from_char, to_char in map(None, fromChars, toChars):
        translate[ord(from_char)] = to_char

    result = reduce(lambda a, b, t=translate: a + (t.get(ord(b), b) or ''),
                    source,
                    '')
    return result
예제 #7
0
def String(context, object=None):
    """Function: <string> string(<object>?)"""
    if type(object) in g_stringTypes:
        return object
    if object is None:
        object = [context.node]
    return Conversions.StringValue(object)
예제 #8
0
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.
    In other words, this function is voodoo.
    """
    (prefix, local) = ExpandQName(funcname, namespaces=context.processorNss)
    func = (g_extFunctions.get(expanded)
            or CoreFunctions.CoreFunctions.get(expanded, None))
    if not func:
        raise Exception('Dynamically invoked function %s not found.' %
                        funcname)
    flist = [f] * len(nodesets)
    lf = lambda x, f, *args: apply(f, args)
    retlist = apply(map, (lf, flist) + nodesets)

    proc = context.processor
    result_nodeset = []
    for ret in retlist:
        proc.pushResult()
        proc.writers[-1].text(Conversions.StringValue(ret))
        frag = proc.popResult()
        context.rtfs.append(frag)
        result_nodeset.append(frag.childNodes[0])
    return result_nodeset
예제 #9
0
def SearchRePy20(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)
    proc = context.processor
    matches_nodeset = []
    _re = re.compile(pattern)
    _match = _re.search(arg)
    while _match:
        proc.pushResult()
        proc.writers[-1].startElement('Match', EMPTY_NAMESPACE)
        _groups = _match.groups()
        # .groups() return empty tuple when the pattern did not do grouping
        if not _groups: _groups = tuple(_match.group())
        for group in _groups:
            proc.writers[-1].startElement('Group', EMPTY_NAMESPACE)
            # MatchObject groups return None if unmatched
            # unlike .findall() returning empty strings
            proc.writers[-1].text(group or '')
            proc.writers[-1].endElement('Group')
        proc.writers[-1].endElement('Match')
        frag = proc.popResult()
        context.rtfs.append(frag)
        matches_nodeset.append(frag.childNodes[0])
        _match = _re.search(arg, _match.end())
    return matches_nodeset
예제 #10
0
def Match(context, pattern, arg=None):
    """Do a regular expression match against the argument"""
    if not arg:
        arg = context.node
    arg = Conversions.StringValue(arg)
    bool = re.match(pattern, arg) and boolean.true or boolean.false
    return bool
예제 #11
0
def Concat(context, *args):
    """Function: <string> concat(<string>, <string>, ...)"""
    if len(args) < 1:
        raise RuntimeException(RuntimeException.WRONG_ARGUMENTS, 'concat',
                               _("at least 2 arguments expected"))
    return reduce(lambda a, b, c=context: a + Conversions.StringValue(b),
                  args,
                  '')
예제 #12
0
def distinct(context, nodeset):
    if type(nodeset) != type([]):
        raise Exception("'distinct' parameter must be of type node-set!")

    nodes = {}
    for node in nodeset:
        nodes[Conversions.StringValue(node)] = node

    return nodes.values()
예제 #13
0
def split(context, arg, delim=None):
    doc = context.node
    while doc.parentNode:
        doc = doc.parentNode

    nodeset = []
    for token in string.split(Conversions.StringValue(arg), delim):
        nodeset.append(doc.createTextNode(token))

    return nodeset
예제 #14
0
def Id(context, object):
    """Function: <node-set> id(<object>)"""
    id_list = []
    if type(object) != type([]):
        st = Conversions.StringValue(object)
        id_list = string.split(st)
    else:
        for n in object:
            id_list.append(Conversions.StringValue(n))
    rt = []
    for id in id_list:
        doc = context.node.ownerDocument or context.node
        elements = Util.ElementsById(doc.documentElement, id)
        if len(elements) > 1:
            raise RuntimeException(RuntimeException.WRONG_ARGUMENTS, 'id',
                                   _("argument not unique"))
        elif elements:
            # Must be 1
            rt.append(elements[0])
    return rt
예제 #15
0
def Substring(context, st, start, end=None):
    """Function: <string> substring(<string>, <number>, <number>?)"""
    st = Conversions.StringValue(st)
    start = Conversions.NumberValue(start)
    if start is NaN:
        return ''
    start = int(round(start))
    start = start > 1 and start - 1 or 0

    if end is None:
        return st[start:]
    end = Conversions.NumberValue(end)
    if start is NaN:
        return st[start:]
    end = int(round(end))
    return st[start:start + end]
예제 #16
0
def Lang(context, lang):
    """Function: <boolean> lang(<string>)"""
    lang = string.upper(Conversions.StringValue(lang))
    node = context.node
    while node:
        lang_attr = filter(lambda x: x.name == 'xml:lang' and x.value,
                           node.attributes.values())
        value = lang_attr and lang_attr[0].nodeValue or None
        if value:
            # See if there is a suffix
            index = string.find(value, '-')
            if index != -1:
                value = value[:index]
            value = string.upper(value)
            return value == lang and boolean.true or boolean.false
        node = node.nodeType == Node.ATTRIBUTE_NODE and node.ownerElement or node.parentNode
    return boolean.false
예제 #17
0
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 = re.findall(pattern, arg)
    proc = context.processor
    matches_nodeset = []
    for groups in matches:
        proc.pushResult()
        proc.writers[-1].startElement('Match', EMPTY_NAMESPACE)
        if type(groups) != type(()):
            groups = (groups, )
        for group in groups:
            proc.writers[-1].startElement('Group', EMPTY_NAMESPACE)
            proc.writers[-1].text(group)
            proc.writers[-1].endElement('Group')
        proc.writers[-1].endElement('Match')
        frag = proc.popResult()
        context.rtfs.append(frag)
        matches_nodeset.append(frag.childNodes[0])
    return matches_nodeset
예제 #18
0
def find(context, outer, inner):
    return string.find(Conversions.StringValue(outer),
                       Conversions.StringValue(inner))
예제 #19
0
def EscapeUrl(context, url):
    "Escape illegal characters in a URL"
    return urllib.quote(Conversions.StringValue(url))
예제 #20
0
def Normalize(context, st=None):
    """Function: <string> normalize-space(<string>?)"""
    if st is None:
        st = context.node
    st = Conversions.StringValue(st)
    return string.join(string.split(st))
예제 #21
0
def StringLength(context, st=None):
    """Function: <number> string-length(<string>?)"""
    if st is None:
        st = context.node
    return len(Conversions.StringValue(st))
예제 #22
0
def Evaluate(context, expr):
    import pyxml.xpath
    return pyxml.xpath.Evaluate(Conversions.StringValue(st), context=context)
예제 #23
0
def join(context, nodeset, delim=None):
    comps = map(lambda x: Conversions.StringValue(x), nodeset)
    if delim:
        return string.joinfields(comps, delim)
    else:
        return string.joinfields(comps)
예제 #24
0
def StartsWith(context, outer, inner):
    """Function: <string> starts-with(<string>, <string>)"""
    outer = Conversions.StringValue(outer)
    inner = Conversions.StringValue(inner)
    return outer[:len(inner)] == inner and boolean.true or boolean.false