-
Notifications
You must be signed in to change notification settings - Fork 0
/
cwm_xml.py
executable file
·209 lines (172 loc) · 7.36 KB
/
cwm_xml.py
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
"""XML built-ins for cwm
"""
from diag import progress, verbosity
from term import LightBuiltIn, Function, ReverseFunction, MultipleFunction, \
HeavyBuiltIn
from llyn import loadToStore # for caching in store's experience
from sax2rdf import XMLtoDOM # for fn:doc
#from Ft.Xml.XPath import Evaluate as evalXPath
# http://packages.debian.org/unstable/python/python-xml
# see also for a review:
# http://www.oreillynet.com/onlamp/blog/2005/01/code_respecting_xpath_xml_pyth.html
##
## The following code allows for the lazy importing of the
## evalXPath function. It is a hack
def evalXPath(*args, **keywords):
try:
from xml.xpath import Evaluate as localEvalXPath
except ImportError:
progress("Try getting python-xml from http://downloads.sourceforge.net/pyxml/PyXML-0.8.4.tar.gz")
localEvalXPath = progress
globals()['evalXPath'] = localEvalXPath
return localEvalXPath(*args, **keywords)
XMLBI_NS_URI = "http://www.w3.org/2007/ont/xml#"
__version__ = "0.1"
# Node properties
# see http://www.python.org/doc/current/lib/dom-node-objects.html
class BI_nodeType(LightBuiltIn, Function):
"""An integer representing the node type
"""
def evaluateObject(self, subj_py):
return subj_py.nodeType
class BI_parentNode(LightBuiltIn, Function):
"""The parent of the current node, or None for the document node.
The value is always a Node object or None. For Element nodes,
this will be the parent element, except for the root element,
in which case it will be the Document object. For Attr nodes, this is always None.
"""
def evaluateObject(self, subj_py):
return subj_py.parentNode
class BI_attributes(LightBuiltIn, Function):
"""A NamedNodeMap of attribute objects. Only elements have
actual values for this.
"""
def evaluateObject(self, subj_py):
return subj_py.attributes
class BI_previousSibling(LightBuiltIn, Function):
"""The node that immediately precedes this one with the same parent.
For instance the element with an end-tag that comes just before the
self element's start-tag. Of course, XML documents are made up of
more than just elements so the previous sibling could be text,
a comment, or something else.
If this node is the first child of the parent, this property will not exist.
"""
def evaluateObject(self, subj_py):
return subj_py.previousSibling
class BI_nextSibling(LightBuiltIn, Function):
"""The node that immediately follows this one with the same parent. See also previousSibling.
If this is the last child of the parent, this property will not exist.
"""
def evaluateObject(self, subj_py):
return subj_py.nextSibling
class BI_childNodes(LightBuiltIn, Function):
"""A list of nodes contained within this node.
"""
def evaluateObject(self, subj_py):
return subj_py.childNodes
class BI_firstChild(LightBuiltIn, Function):
"""The first child of the node, if there are any.
"""
def evaluateObject(self, subj_py):
return subj_py.firstChild
class BI_lastChild(LightBuiltIn, Function):
"""The last child of the node, if there are any.
"""
def evaluateObject(self, subj_py):
return subj_py.lastChild
class BI_localName(LightBuiltIn, Function):
"""The part of the tagName following the colon if there is one, else the entire tagName
"""
def evaluateObject(self, subj_py):
return subj_py.localName
class BI_prefix(LightBuiltIn, Function):
"""The part of the tagName preceding the colon if there is one, else the empty string
"""
def evaluateObject(self, subj_py):
return subj_py.prefix
class BI_namespaceURI(LightBuiltIn, Function):
"""The namespace associated with the element name.
"""
def evaluateObject(self, subj_py):
return subj_py.namespaceURI
class BI_nodeName(LightBuiltIn, Function):
"""This has a different meaning for each node type; see the DOM
specification for details. You can always get the information you would
get here from another
property such as the tagName property for elements or
the name property for attributes.
"""
def evaluateObject(self, subj_py):
return subj_py.nodeName
class BI_nodeValue(LightBuiltIn, Function):
"""This has a different meaning for each node type;
see the DOM specification for details.
The situation is similar to that with nodeName
"""
def evaluateObject(self, subj_py):
return subj_py.nodeValue
class BI_hasAttributes(LightBuiltIn, Function):
"""True if the node has any attributes.
"""
def evaluateObject(self, subj_py):
return subj_py.hasAttributes()
class BI_hasChildNodes(LightBuiltIn, Function):
"""True if the node has any child nodes
"""
def evaluateObject(self, subj_py):
return subj_py.hasChildNodes()
class BI_isSameNode(LightBuiltIn):
"""Returns true if other refers to the same node as this node.
This is especially useful for DOM implementations which use
any sort of proxy architecture (because more than one object can refer to the same node).
"""
def evaluate(self, subj_py, obj_py):
return subj_py.sSameNode(obj_py)
class BI_xpath(LightBuiltIn, MultipleFunction):
"""Evaluate XPath expression and bind to each resulting node."""
def evaluateObject(self, subj_py):
node, expr = subj_py
out = evalXPath(expr, node)
return [self.store.newXMLLiteral(n) for n in out]
class BI_doc(HeavyBuiltIn, Function):
"""Load XML document from the web. subject is a string, per XQuery.
see test/xml-syntax/fn_doc1.n3
see also llyn.BI_xmlTree, which seems to be dead code
"""
def evalObj(self, subj, queue, bindings, proof, query):
progress("@@fn:doc", subj)
# fn:doc takes a string, but the llyn cache keys of symbols
sym = subj.store.newSymbol(subj.value())
try:
lit = loadToStore(sym, ["application/xml", "text/xml"])
except IOError, e:
progress("@@ioerror", e)
return None # hmm... is built-in API evolving to support exceptions?
dom = XMLtoDOM(lit.value())
# odd... why does BI_xmlTree use the pair API rather than newXMLLiteral?
progress("@@fn:doc returning")
return lit.store.newXMLLiteral(dom)
# Register the string built-ins with the store
def register(store):
str = store.symbol(XMLBI_NS_URI[:-1])
str.internFrag("nodeType", BI_nodeType)
str.internFrag("parentNode", BI_parentNode)
str.internFrag("attributes", BI_attributes)
str.internFrag("previousSibling", BI_previousSibling)
str.internFrag("nextSibling", BI_nextSibling)
str.internFrag("childNodes", BI_childNodes)
str.internFrag("firstChild", BI_firstChild)
str.internFrag("lastChild", BI_lastChild)
str.internFrag("localName", BI_localName)
str.internFrag("prefix", BI_prefix)
str.internFrag("namespaceURI", BI_namespaceURI)
str.internFrag("nodeName", BI_nodeName)
str.internFrag("nodeValue", BI_nodeValue)
str.internFrag("hasAttributes", BI_hasAttributes)
str.internFrag("hasChildNodes", BI_hasChildNodes)
str.internFrag("isSameNode", BI_isSameNode)
str.internFrag("xpath", BI_xpath) # needs test, docs
fn = store.symbol("http://www.w3.org/2006/xpath-functions")
fn.internFrag("string", BI_nodeValue) # probably not an exact match
fn.internFrag("doc", BI_doc)
# ends