1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
|
########################################################################
#
# File Name: Conversions.py
#
#
"""
The implementation of all of the core functions for the XPath spec.
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 string, cStringIO
from xml.dom import Node
from xml.xpath import ExpandedNameWrapper
from xml.xpath import NamespaceNode
from xml.xpath import NaN, Inf
from xml.xpath import Util
from xml.xpath import NAMESPACE_NODE
from xml.utils import boolean
import types
try:
g_stringTypes= [types.StringType, types.UnicodeType]
except:
g_stringTypes= [types.StringType]
def BooleanEvaluate(exp, context):
rt = exp.evaluate(context)
return BooleanValue(rt)
def StringValue(object):
#def StringValue(object, context=None):
#print "StringValue context", context
#if context:
# cache = context.stringValueCache
#else:
# cache = None
for func in g_stringConversions:
#handled, result = func(object, cache)
handled, result = func(object)
if handled:
break
else:
result = None
return result
def BooleanValue(object):
for func in g_booleanConversions:
handled, result = func(object)
if handled:
break
else:
result = None
return result
def NumberValue(object):
for func in g_numberConversions:
handled, result = func(object)
if handled:
break
else:
result = None
return result
def NodeSetValue(object):
for func in g_nodeSetConversions:
handled, result = func(object)
if handled:
break
else:
result = None
return result
def CoreStringValue(object):
"""Get the string value of any object"""
# See bottom of file for conversion functions
result = _strConversions.get(type(object), _strUnknown)(object)
return result is not None, result
def CoreNumberValue(object):
"""Get the number value of any object"""
if type(object) in [type(1), type(2.3), type(4L)]:
return 1, object
elif boolean.IsBooleanType(object):
return 1, int(object)
#FIXME: This can probably be optimized
object = StringValue(object)
try:
object = float(object)
except:
#Many platforms seem to have a problem with strtod() and NaN: reported on Windows and FreeBSD
#object = float('NaN')
if object == '':
object = 0
else:
object = NaN
return 1, object
CoreBooleanValue = lambda obj: (1, boolean.BooleanValue(obj, StringValue))
g_stringConversions = [CoreStringValue]
g_numberConversions = [CoreNumberValue]
g_booleanConversions = [CoreBooleanValue]
#g_nodeSetConversions = [CoreNodeSetValue]
# Conversion functions for converting objects to strings
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
def _strInstance(object):
if hasattr(object, 'stringValue'):
return object.stringValue
if hasattr(object, 'nodeType'):
node_type = object.nodeType
if node_type == Node.ELEMENT_NODE:
# The concatenation of all text descendants
text_elem_children = filter(lambda x:
x.nodeType in [Node.TEXT_NODE, Node.ELEMENT_NODE, Node.CDATA_SECTION_NODE],
object.childNodes)
return reduce(lambda x, y:
CoreStringValue(x)[1] + CoreStringValue(y)[1],
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, Node.CDATA_SECTION_NODE]:
return object.data
if node_type == Node.DOCUMENT_NODE:
# Use the String value of the document root
return CoreStringValue(object.documentElement)
return None
_strConversions = {
types.StringType : str,
types.IntType : str,
types.LongType : lambda l: repr(l)[:-1],
types.FloatType : lambda f: f is NaN and 'NaN' or '%g' % f,
boolean.BooleanType : str,
types.InstanceType : _strInstance,
types.ListType : lambda x: x and _strConversions.get(type(x[0]), _strUnknown)(x[0]) or '',
}
if hasattr(types, 'UnicodeType'):
_strConversions[types.UnicodeType] = unicode
try:
from Ft.Lib import cDomlettec
def _strElementInstance(object):
if hasattr(object, 'stringValue'):
return object.stringValue
if object.nodeType == Node.ELEMENT_NODE:
# The concatenation of all text descendants
text_elem_children = filter(
lambda x: x.nodeType in [Node.TEXT_NODE, Node.ELEMENT_NODE, Node.CDATA_SECTION_NODE],
object.childNodes
)
return reduce(lambda x, y:
CoreStringValue(x)[1] + CoreStringValue(y)[1],
text_elem_children,
'')
_strConversions.update({
cDomlettec.DocumentType : lambda x: _strElementInstance(x.documentElement),
cDomlettec.ElementType : _strElementInstance,
cDomlettec.TextType : lambda x: x.data,
cDomlettec.CommentType : lambda x: x.data,
cDomlettec.ProcessingInstructionType : lambda x: x.data,
cDomlettec.AttrType : lambda x: x.value,
})
except ImportError:
pass
|