SortElement.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 » SortElement.py
########################################################################  
# $Header: /var/local/cvsroot/4Suite/Ft/Xml/Xslt/SortElement.py,v 1.6 2005/02/09 11:21:20 mbrown Exp $
"""
xsl:sort implementation
    
Copyright 2005 Fourthought, Inc. (USA).
Detailed license and copyright information: http://4suite.org/COPYRIGHT
Project home, documentation, distributions: http://4suite.org/
"""

from Ft.Lib import number
from Ft.Xml import EMPTY_NAMESPACE
from Ft.Xml.XPath import Conversions
from Ft.Xml.Xslt import XsltElement
#from Ft.Xml.Xslt import XsltException, Error
from Ft.Xml.Xslt import CategoryTypes,ContentInfo,AttributeInfo

class SortElement(XsltElement):
    category = None
    content = ContentInfo.Empty
    legalAttrs = {
        'select' : AttributeInfo.StringExpression(default='.'),
        'lang' : AttributeInfo.NMTokenAvt(),
        # We don't support any additional data-types, hence no
        # AttributeInfo.QNameButNotNCName()
        'data-type' : AttributeInfo.ChoiceAvt(['text', 'number'],
                                              default='text'),
        'order' : AttributeInfo.ChoiceAvt(['ascending', 'descending'],
                                          default='ascending'),
        'case-order' : AttributeInfo.ChoiceAvt(['upper-first', 'lower-first']),
        }

    doesSetup = 1

    def setup(self):
        # optimize for constant AVT attribute values (i.e., no {})
        if self._data_type.isConstant() and self._order.isConstant() and \
           self._case_order.isConstant():
            self._comparer = self.makeComparer(self._order.evaluate(None),
                                               self._data_type.evaluate(None),
                                               self._case_order.evaluate(None),
                                               )
        else:
            self._comparer = None
        return

    def makeComparer(self, order, data_type, case_order):
        #if order not in ['ascending', 'descending']:
        #    raise XsltException(Error.ILLEGAL_SORT_ORDER_VALUE)
        #if data_type not in ['text', 'number']:
        #    raise XsltException(Error.ILLEGAL_SORT_DATA_TYPE_VALUE)
        #if case_order and case_order not in ['upper-first', 'lower-first']:
        #    raise XsltException(Error.ILLEGAL_SORT_CASE_ORDER_VALUE)

        if data_type == 'number':
            comparer = FloatCompare
        else:
            if case_order == 'lower-first':
                comparer = LowerFirstCompare
            elif case_order == 'upper-first':
                comparer = UpperFirstCompare
            else:
                # use default for this locale
                comparer = cmp

        if order == 'descending':
            comparer = Descending(comparer)

        return comparer

    def getComparer(self, context):
        if self._comparer: return self._comparer

        data_type = self._data_type.evaluate(context)
        order = self._order.evaluate(context)
        case_order = self._case_order and self._case_order.evaluate(context)
        return self.makeComparer(order, data_type, case_order)

    def evaluate(self, context):
        return Conversions.StringValue(self._select.evaluate(context))


### Comparision Functions ###

class Descending:
    def __init__(self, comparer):
        self.comparer = comparer

    def __call__(self, a, b):
        return self.comparer(b, a)

def FloatCompare(a, b):
    a = float(a or 0)
    b = float(b or 0)
    
    # NaN seems to always equal everything else, so we'll do it ourselves
    # the IEEE definition of NaN makes it the largest possible number
    if number.isnan(a):
        if number.isnan(b):
            return 0
        else:
            return -1
    elif number.isnan(b):
        return 1

    return cmp(a, b)
        
def LowerFirstCompare(a, b):
    # case only matters if the strings are equal ignoring case
    if a.lower() == b.lower():
        for i in xrange(len(a)):
            if a[i] != b[i]:
                return a[i].islower() and -1 or 1
        # they are truly equal
        return 0
    else:
        return cmp(a, b)

def UpperFirstCompare(a, b):
    # case only matters if the strings are equal ignoring case
    if a.lower() == b.lower():
        for i in xrange(len(a)):
            if a[i] != b[i]:
                return a[i].isupper() and -1 or 1
        # they are truly equal
        return 0
    else:
        return cmp(a, b)
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.