-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdatamodel.py
More file actions
executable file
·135 lines (116 loc) · 3.38 KB
/
datamodel.py
File metadata and controls
executable file
·135 lines (116 loc) · 3.38 KB
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
"""This module contains basic functions for quering the xpath data
model, and the building blocks for evaluating xpath exspresions.
"""
from types import InstanceType, BooleanType, FloatType, StringTypes
from itertools import ifilter, chain, imap
from operator import concat, lt, le, eq, ne, ge, gt
from xml.dom import Node
#Functions not directly related to the data model
def aggregate(function, seed, iterable) :
"Generic function operating in a sequence"
for i in iterable :
seed = function(seed, i)
return seed
def any(seq, pred=bool):
"Returns True if pred(x) is True for at least one element in the iterable"
for elem in ifilter(pred, seq):
return True
return False
#functions quereing information from the dom
def allDescendants(node) :
for child in node.childNodes :
yield child
for descendant in allDescendants(child) :
yield descendant
def allDescendantsAndSelf(node) :
yield node
for descendant in allDescendants(node) :
yield descendant
use_node_value = [Node.ATTRIBUTE_NODE, Node.TEXT_NODE,
Node.CDATA_SECTION_NODE, Node.PROCESSING_INSTRUCTION_NODE,
Node.COMMENT_NODE ]
def string_value(node) :
"This is the string-value that the xpath spec speaks of."
if node.nodeType == Node.ELEMENT_NODE or node.nodeType == Node.DOCUMENT_NODE :
return aggregate(
concat,
"",
imap(lambda n : n.nodeValue,
ifilter(
lambda node : node.nodeType in [Node.TEXT_NODE, Node.CDATA_SECTION_NODE],
allDescendantsAndSelf(node)))
)
if node.nodeType in use_node_value :
return node.nodeValue
#Casting xpath types, These functions can operate on packed objects
def unPack(i) :
if type(i) in StringTypes :
return i
if not isaSequence(i) :
return i
try :
first = iter(i).next()
except StopIteration :
return []
t = type(first)
if t is InstanceType :
return chain([first], i)
else :
return first
def isaSequence(i) :
if type(i) in StringTypes :
return False
try :
iter(i)
except :
return False;
return True
def isEmptySequence(i) :
"Only workes on unpacked sequences"
return i == []
def boolean(n) :
unpacked = unPack(n)
if isaSequence(unpacked) :
return not isEmptySequence(unpacked)
t = type(unpacked)
if t is BooleanType :
return unpacked
if t is FloatType :
return unpacked != 0
if t in StringTypes :
return unpacked != ""
raise "Hell"
def number(n) :
unpacked = unPack(n)
if isaSequence(unpacked) or type(unpacked) == InstanceType:
return float(string(unpacked))
t = type(unpacked)
if t is BooleanType :
if unpacked : return float(1)
else : return float(0)
if t is FloatType :
return unpacked
if t in StringTypes :
return float(unpacked)
raise "Hell"
def string(n) :
unpacked = unPack(n)
if isaSequence(unpacked) :
if isEmptySequence(unpacked) :
return u""
else :
return string_value(iter(unpacked).next())
t = type(unpacked)
if t is BooleanType :
if unpacked : return u"true"
else : return u"false"
if t is FloatType :
if unpacked % 1 == 0 :
return "%d" % unpacked
else :
return "%f" % unpacked
if t is InstanceType :
return string_value(unpacked)
if t in StringTypes :
return unpacked
raise "Hell"