Viewing file: Conversions.py (4.02 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
######################################################################## # # File Name: Conversions.py # # Docs: http://docs.4suite.org/XPATH/Conversions.py.html # """ The implementation of the XPath object type conversions. WWW: http://4suite.org/XPATH e-mail: support@4suite.org
Copyright (c) 2000-2001 Fourthought Inc, USA. All Rights Reserved. See http://4suite.org/COPYRIGHT for license and copyright information """
import types from xml.dom import Node
from Ft.Lib import number, boolean
StringValue = lambda obj: _strConversions.get(type(obj), _strUnknown)(obj)
NumberValue = lambda obj: _numConversions.get(type(obj), _numUnknown)(obj)
BooleanValue = lambda obj: _boolConversions.get(type(obj), _boolUnknown)(obj)
# -- String Conversions ----------------------------------------------
def _strUnknown(object): # Allow for non-instance DOM node objects if hasattr(object, 'nodeType'): # Add this type to the mapping for next time through _strConversions[type(object)] = _strInstance return _strInstance(object) return u''
def _strInstance(object): if hasattr(object, 'stringValue'): return object.stringValue elif hasattr(object, 'nodeType'): node_type = object.nodeType if node_type in [Node.ELEMENT_NODE, Node.DOCUMENT_NODE]: # The concatenation of all text descendants text_elem_children = filter(lambda x: x.nodeType in [Node.TEXT_NODE, Node.ELEMENT_NODE], object.childNodes) return reduce(lambda x, y: StringValue(x) + StringValue(y), text_elem_children, '') if node_type in [Node.ATTRIBUTE_NODE, NAMESPACE_NODE]: return object.value if node_type in [Node.PROCESSING_INSTRUCTION_NODE, Node.COMMENT_NODE, Node.TEXT_NODE]: return object.data return u''
def _strFloat(float): if number.finite(float): if float == round(float): return unicode(str(long(float))) else: # 12 digits is how many Python uses for str() return u'%0.12g' % float elif number.isnan(float): return u'NaN' elif float < 0: return u'-Infinity' else: return u'Infinity'
_strConversions = { types.StringType : unicode, types.UnicodeType : unicode, types.IntType : lambda i: unicode(str(i)), types.LongType : lambda l: unicode(str(l)), types.FloatType : _strFloat, boolean.BooleanType : lambda b: unicode(str(b)), types.InstanceType : _strInstance, types.ListType : lambda x: x and _strConversions.get(type(x[0]), _strUnknown)(x[0]) or u'', }
# -- Number Conversions ----------------------------------------------
def _numString(string): try: # From XPath 1.0, sect 4.4 - number(): # Any string that does not match "S? '-'? Number" is converted to NaN # S ::= [\x20\x09\x0A\x0D]* # Digits ::= [0-9]+ # Number ::= Digits ('.' Digits?)? | '.' Digits return float(string) except: # Many platforms seem to have a problem with strtod('nan'), # reported on Windows and FreeBSD return number.nan
_numUnknown = lambda object: _numString(StringValue(object))
_numConversions = { types.IntType : float, types.LongType : float, types.FloatType : float, boolean.BooleanType : float, types.StringType : _numString, types.UnicodeType : _numString, }
# -- Boolean Conversions ---------------------------------------------
_boolConversions = { boolean.BooleanType : boolean.bool, types.IntType : boolean.bool, types.LongType : boolean.bool, types.FloatType : boolean.bool, types.StringType : boolean.bool, types.UnicodeType : boolean.bool, types.ListType : boolean.bool, }
_boolUnknown = lambda object: boolean.bool(StringValue(object))
try: # Use C optimized functions, if available from _conversions import * except: from Ft.Xml.XPath import NAMESPACE_NODE
|