Beispiel #1
0
def pipp_link(context, link):
    """Record a link"""
    ctx = context.processor.extensionParams[(NAMESPACE, 'context')]
    new_node = ctx.state_doc.createElementNS(EMPTY_NAMESPACE,
                                             Conversions.StringValue('link'))
    new_node.appendChild(
        ctx.state_doc.createTextNode(Conversions.StringValue(link)))
    ctx.links_node.appendChild(new_node)
Beispiel #2
0
def EndsWith(context, outer, inner):
    """
    Returns true if the string given in the first argument ends with
    the substring given in the second argument.
    """
    outer = Conversions.StringValue(outer)
    inner = Conversions.StringValue(inner)
    return outer.endswith(inner) and boolean.true or boolean.false
def Match(context, source, pattern, flags=''):
    """
    The regexp:match function lets you get hold of the substrings of the
    string passed as the first argument that match the captured parts of
    the regular expression passed as the second argument.

    The second argument is a regular expression that follows the Javascript
    regular expression syntax.

    The third argument is a string consisting of character flags to be used
    by the match. If a character is present then that flag is true. The
    flags are:
      g: global match - the submatches from all the matches in the string
                        are returned. If this character is not present, then
                        only the submatches from the first match in the
                        string are returned.
      i: case insensitive - the regular expression is treated as case
                            insensitive. If this character is not present,
                            then the regular expression is case sensitive.

    The regexp:match function returns a node set of 'match' elements, each of
    whose string value is equal to a portion of the first argument string
    that was captured by the regular expression. If the match is not global,
    the first match element has a value equal to the portion of the string
    matched by the entire regular expression.
    """
    source = Conversions.StringValue(source)
    pattern = Conversions.StringValue(pattern)
    flags = flags and Conversions.StringValue(flags)

    regexp = re.compile(pattern, 'i' in flags and re.IGNORECASE or 0)

    match = regexp.search(source)
    if match is None:
        return []
    processor = context.processor
    processor.pushResultTree(context.currentInstruction.baseUri)
    try:
        if 'g' in flags:
            # find all matches in the source
            while match:
                processor.writer.startElement(u'match')
                # return everything that matched the pattern
                processor.writer.text(match.group())
                processor.writer.endElement(u'match')
                match = regexp.search(source, match.end())
        else:
            # the first 'match' element contains entire matched text
            all = [match.group()]
            groups = match.groups()
            groups and all.extend(list(groups))
            for match in all:
                processor.writer.startElement(u'match')
                match and processor.writer.text(match)
                processor.writer.endElement(u'match')
    finally:
        rtf = processor.popResult()
    return rtf.childNodes
def Contains(context, outer, inner):
    """Function: <string> contains(<string>, <string>)"""
    if not isinstance(outer, XPathStringType):
        outer = Conversions.StringValue(outer)
    if not isinstance(inner, XPathStringType):
        inner = Conversions.StringValue(inner)
    if not inner:
        return boolean.true
    return outer.find(inner) >= 0 and boolean.true or boolean.false
def StartsWith(context, outer, inner):
    """Function: <string> starts-with(<string>, <string>)"""
    if not isinstance(outer, XPathStringType):
        outer = Conversions.StringValue(outer)
    if not isinstance(inner, XPathStringType):
        inner = Conversions.StringValue(inner)
    if not inner:
        return boolean.true
    return outer[:len(inner)] == inner and boolean.true or boolean.false
Beispiel #6
0
def ResolvePath(context, base, rel):
    """
    Resolves a Posix-style path, such as the path portion of a URL,
    against a base. Similar to f:resolve-url, but allows the base to be
    just a path, not necessarily a full URL.
    """
    base = Conversions.StringValue(base)
    rel = Conversions.StringValue(rel)
    return Uri.BaseJoin(base, rel)
Beispiel #7
0
def Constant(context, name, precision):
    """
    The math:constant function returns the specified constant to a set precision.
    """
    name = Conversions.StringValue(name)
    if not CONSTANTS.has_key(name):
        return number.nan

    precision = Conversions.NumberValue(precision)
    return float('%0.*f' % (int(precision), CONSTANTS[name]))
Beispiel #8
0
    def check_uniqueness(self, context, nodes):
        '''available in XPath as check-uniqueness'''
        hash = {}

        for n in nodes:
            h = self.nodeUID(n)
            if (hash.has_key(h)):
                return Conversions.BooleanValue(0)
            hash[h] = 1

        return Conversions.BooleanValue(1)
Beispiel #9
0
def ATan2(context, y, x):
    """
    The math:atan2 function returns the angle ( in radians ) from the X axis
    to a point (y,x).
    """
    x = Conversions.NumberValue(x)
    y = Conversions.NumberValue(y)
    try:
        return math.atan2(y, x)
    except ValueError:
        return number.nan
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
Beispiel #11
0
def ResolveUrl(context, base, rel):
    """
    Returns the relative URL ref given in the second argument
    resolved against the base given in the first argument.
    In case of URI processing error an empty string is returned
    """
    base = Conversions.StringValue(base)
    rel = Conversions.StringValue(rel)
    try:
        return Uri.Absolutize(rel, base)
    except Uri.UriException:
        return u''
Beispiel #12
0
def pipp_import_join(context, name, join_str):
    ctx = context.processor.extensionParams[(NAMESPACE, 'context')]
    name = Conversions.StringValue(name)
    cur_doc = ctx.state_node
    values = []
    while cur_doc:
        ctx.add_edepends(cur_doc.getAttributeNS(EMPTY_NAMESPACE, 'src'), name)
        nodes = cur_doc.xpath("exports/*[name()='%s']" % name.replace("'", ""))
        if nodes:
            values.insert(0, get_text(nodes[0]))
        cur_doc = cur_doc.parentNode.parentNode
    return Conversions.StringValue(join_str).join(values)
Beispiel #13
0
    def evaluate(self, context):
        """Returns a boolean"""
        left = self._left.evaluate(context)
        right = self._right.evaluate(context)

        if isinstance(left, Types.NodesetType) or \
           isinstance(right, Types.NodesetType):
            return _nodeset_compare(self._cmp, left, right, relational=True)

        left = Conversions.NumberValue(left)
        right = Conversions.NumberValue(right)
        return self._cmp(left, right) and boolean.true or boolean.false
Beispiel #14
0
def Wrap(context, text, width):
    """
    f:wrap() returns a string with the text reflowed so that each line
    fits within the given width. Existing linefeeds are preserved, but
    spaces are considered inter-word separators that can be collapsed.
    To reflow without preserving existing linefeeds, strip them first,
    e.g. with translate(text, '&#10;', '').
    http://lists.fourthought.com/pipermail/4suite-dev/2002-December/000878.html
    """
    s = Conversions.StringValue(text)
    width = Conversions.NumberValue(width)
    return LineWrap(s, width)
Beispiel #15
0
def SubstringAfter(context, outer, inner):
    """Function: <string> substring-after(<string>, <string>)"""
    if not isinstance(outer, XPathStringType):
        outer = Conversions.StringValue(outer)
    if not isinstance(inner, XPathStringType):
        inner = Conversions.StringValue(inner)
    if not inner:
        return u''
    index = outer.find(inner)
    if index == -1:
        return u''
    return outer[index + len(inner):]
Beispiel #16
0
 def evaluate(self, context):
     '''Returns a number'''
     if self._leftLit:
         lrt = self._left
     else:
         lrt = self._left.evaluate(context)
         lrt = Conversions.NumberValue(lrt)
     if self._rightLit:
         rrt = self._right
     else:
         rrt = self._right.evaluate(context)
         rrt = Conversions.NumberValue(rrt)
     return lrt + (rrt * self._sign)
Beispiel #17
0
def Padding(context, length, chars=None):
    """
    The str:padding function creates a padding string of a certain length.

    The second argument gives a string to be used to create the padding.
    This string is repeated as many times as is necessary to create a string
    of the length specified by the first argument; if the string is more than
    a character long, it may have to be truncated to produce the required
    length. If no second argument is specified, it defaults to a space (' ').
    """
    length = int(Conversions.NumberValue(length))
    chars = chars and Conversions.StringValue(chars) or u' '
    return (chars * length)[:length]
Beispiel #18
0
def ParseDate(context, date, format=None):
    """
    This function is similar to EXSLT's date:parse-date()
    except that it uses Python rather than Java conventions
    for the date formatting.
    """
    import time
    date = Conversions.StringValue(date)
    format = Conversions.StringValue(format)
    time_tuple = time.strptime(format)
    #perhaps add some variants for missing time tuple values?
    str_time = time.strftime("%Y-%m-%dT%H:%M:%S", time_tuple)
    return unicode(str_time, 'us-ascii', errors='replace')
Beispiel #19
0
def StrFTime(context, format, date=None):
    """
    Returns the given ISO 8601 UTC date-time formatted according to
    the given format string as would be used by Python's
    time.strftime(). If no date-time string is given, the current
    time is used.
    """
    format = Conversions.StringValue(format)
    if date is not None:
        date = Conversions.StringValue(date)
        time_str = time.strftime(format, time.strptime(date, '%Y-%m-%dT%H:%M:%SZ'))
    else:
        time_str = time.strftime(format)
    return unicode(time_str, 'us-ascii', errors='replace')
Beispiel #20
0
def Replace(context, old, new, arg=None):
    """
    Returns the third argument string, which defaults to the
    string-value of the context node, with occurrences of the substring
    given in the first argument replaced by the string given in the
    second argument.
    See also: EXSLT's str:replace()
    """
    if not arg:
        arg = context.node
    arg = Conversions.StringValue(arg)
    old = Conversions.StringValue(old)
    new = Conversions.StringValue(new)
    return arg.replace(old, new)
Beispiel #21
0
 def __init__(self, sign, left, right):
     self._sign = sign
     self._leftLit = 0
     self._rightLit = 0
     if isinstance(left, ParsedLiteralExpr):
         self._leftLit = 1
         self._left = Conversions.NumberValue(left.evaluate(None))
     else:
         self._left = left
     if isinstance(right, ParsedLiteralExpr):
         self._rightLit = 1
         self._right = Conversions.NumberValue(right.evaluate(None))
     else:
         self._right = right
     return
Beispiel #22
0
def StringLength(context, st=None):
    """Function: <number> string-length(<string>?)"""
    if st is None:
        st = context.node
    if not isinstance(st, XPathStringType):
        st = Conversions.StringValue(st)
    return float(len(st))
Beispiel #23
0
def Seconds(context, string=None):
    """
    The date:seconds function returns the number of seconds specified by the
    argument string. If no argument is given, then the current local
    date/time, as returned by date:date-time is used as a default argument.

    Implements version 1.
    """
    if string is None:
        string = str(_DateTime.now())
    else:
        string = Conversions.StringValue(string)

    try:
        if 'P' in string:
            # its a duration
            duration = _Duration.parse(string)
        else:
            # its a dateTime
            dateTime = _DateTime.parse(
                string, ('dateTime', 'date', 'gYearMonth', 'gYear'))
            duration = _difference(_EPOCH, dateTime)
    except ValueError:
        return number.nan

    # The number of years and months must both be equal to zero
    if duration.years or duration.months:
        return number.nan

    # Convert the duration to just seconds
    seconds = (duration.days * 86400 + duration.hours * 3600 +
               duration.minutes * 60 + duration.seconds)
    if duration.negative:
        seconds *= -1
    return seconds
Beispiel #24
0
def Normalize(context, st=None):
    """Function: <string> normalize-space(<string>?)"""
    if st is None:
        st = context.node
    if not isinstance(st, XPathStringType):
        st = Conversions.StringValue(st)
    return u' '.join(st.split())
Beispiel #25
0
def EscapeXml(context, text):
    """
    Returns the given string with XML markup characters "&", "<" and
    ">" escaped as "&amp;", "&lt;" and "&gt;", respectively.
    """
    from xml.sax.saxutils import escape
    return escape(Conversions.StringValue(text))
Beispiel #26
0
def Lang(context, lang):
    """Function: <boolean> lang(<string>)"""
    lang = Conversions.StringValue(lang).lower()
    node = context.node
    while node.parentNode:
        for attr in node.attributes.values():
            # Search for xml:lang attribute
            if (attr.localName == 'lang'
                    and attr.namespaceURI == XML_NAMESPACE):
                value = attr.nodeValue.lower()
                # Exact match (PrimaryPart and possible SubPart)
                if value == lang:
                    return boolean.true

                # Just PrimaryPart (ignore '-' SubPart)
                index = value.find('-')
                if index != -1 and value[:index] == lang:
                    return boolean.true

                # Language doesn't match
                return boolean.false

        # Continue to next ancestor
        node = node.parentNode

    # No xml:lang declarations found
    return boolean.false
Beispiel #27
0
def Id(context, object_):
    """Function: <node-set> id(<object>)"""
    if not isinstance(object_, NodesetType):
        st = Conversions.StringValue(object_)
        id_list = st.split()
    else:
        id_list = [Conversions.StringValue(n) for n in object_]

    id_list = Set.Unique(id_list)
    doc = context.node.rootNode
    nodeset = []
    for id in id_list:
        element = doc.getElementById(id)
        if element:
            nodeset.append(element)
    return nodeset
Beispiel #28
0
 def instantiate(self, context, processor):
     doc = context.node.rootNode
     if self._raw.evaluate(context):
         processor.xslMessage(repr(context.varBindings))
     else:
         from Ft.Xml.XPath.XPathTypes import g_xpathPrimitiveTypes
         from Ft.Xml.Xslt.CopyOfElement import CopyNode
         writer = processor.writer
         writer.startElement(u'zz:VarDump', RESERVED_NAMESPACE)
         for k, v in context.varBindings.items():
             writer.startElement(u'zz:Var', RESERVED_NAMESPACE)
             #FIXME: should try to join back prefix to var name
             writer.attribute(u'name', k[1], EMPTY_NAMESPACE)
             if isinstance(v, list):
                 # NOTE - this must be before the primitive check due to
                 #  the fact that a node-set is a primitive type
                 for node in v:
                     if node.nodeType == Node.ATTRIBUTE_NODE:
                         processor.writer.comment(
                             u"Attribute: %s=%s" %
                             (node.nodeName, node.value))
                     else:
                         CopyNode(processor, node)
             elif type(v) in g_xpathPrimitiveTypes:
                 writer.text(Conversions.StringValue(v))
             elif hasattr(v, 'nodeType'):
                 CopyNode(processor, v)
             writer.endElement(u'zz:Var', RESERVED_NAMESPACE)
         writer.endElement(u'zz:VarDump', RESERVED_NAMESPACE)
     return
Beispiel #29
0
def pipp_map_view(context, xslt_file):
    ctx = context.processor.extensionParams[(NAMESPACE, 'context')]

    #--
    # Create the XSLT processor object. For efficiency there is a cache of these.
    #--
    xslt_file = ctx.abs_in_path(Conversions.StringValue(xslt_file))
    ctx.add_depends(xslt_file[len(ctx.in_root):])
    processor = processors.get(xslt_file)
    if not processor:
        processor = Processor.Processor()
        processor.registerExtensionModules(['pipp_xslt'])
        processor.appendStylesheet(
            InputSource.DefaultFactory.fromString(
                open(xslt_file).read(), xslt_file))
    processor.extensionParams[(NAMESPACE, 'context')] = ctx

    #--
    # Run the processor against state.xml and return the output.
    # If successful, store the processor object in a cache
    #--
    input = InputSource.DefaultFactory.fromUri(OsPathToUri(ctx.state_xml))
    output = processor.run(input)
    processors[xslt_file] = processor
    return output
Beispiel #30
0
def pipp_child(context, file_name):
    ctx = context.processor.extensionParams[(NAMESPACE, 'context')]
    file_name = ctx.abs_in_path(Conversions.StringValue(file_name)) \
                                [len(ctx.in_root):]
    new_node = ctx.state_doc.createElementNS(EMPTY_NAMESPACE, 'page')
    new_node.setAttributeNS(EMPTY_NAMESPACE, 'src', file_name)
    ctx.children_node.appendChild(new_node)