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 210 211 212 213 214 215 216 217 218 219 220
|
from xml.dom import Node
from xml.dom import EMPTY_NAMESPACE as NULL_NAMESPACE
from xml.dom import EMPTY_PREFIX as NULL_PREFIX
from Ft.Xml.XPath.Context import Context
#from Ft.Xml.Xslt.XsltContext import XsltContext
from Ft.Xml.XPath import Evaluate
from Ft.Xml import SplitQName
from Ft.Xml import XML_NAMESPACE as XML_NS
#FIXME: Use 4Suite L10N
def _(t): return t
class dummy_node_wrapper(object):
@property
def docIndex(self):
return 0
#docIndex = property(_docIndex)
def _xpathAttributes(self):
return []
xpathAttributes = property(_xpathAttributes)
def _childNodes(self):
return []
childNodes = property(_childNodes)
def __cmp__(self, other):
return cmp(self.docIndex, other.docIndex)
class xpath_attr_wrapper(dummy_node_wrapper):
nodeType = Node.ATTRIBUTE_NODE
def __init__(self, qname, ns, value, parent):
self.namespaceURI = ns
self.prefix, self.localName = SplitQName(qname)
self.value = value
self.nodeValue = value
self.name = qname
self.nodeName = qname
self.rootNode = parent._rootNode()
#self.docIndex = id(value)
return
def __unicode__(self):
return self.value
class text_wrapper(dummy_node_wrapper):
nodeType = Node.TEXT_NODE
def __init__(self, st, parent):
self.data = st
self.parentNode = parent
#self.docIndex = id(st)
return
def __unicode__(self):
return self.data
def _rootNode(self):
return self.parentNode._rootNode()
rootNode = property(_rootNode)
ownerDocument = rootNode
@property
def docIndex(self):
#print "text_wrapper._docIndex"
return 1
#docIndex = property(_docIndex)
class xpath_wrapper_container_mixin(object):
def xml_xpath(self, query):
"""
Execute an XPath query with this object standing in for the
context node. The namespace mappings are taken from the root
binding object. There are no variable bindings. Most XPath
is supported.
query - a unicode object expressing an XPath
The return value depends on the XPath expression (expr)
- If expr reults in an XPath string, the return value is a
Python Unicode object
- If expr reults in an XPath number, the return value is a
Python float
- If expr reults in an XPath boolean, the return value is a
Python bool object
- If expr reults in an XPath node set, the return value is a
Python list (always a list, even if empty, or a node with just
one entry)
"""
prefixes = self.rootNode.xmlns_prefixes
if u'xml' not in prefixes:
prefixes.update({u'xml': XML_NS})
ctx = Context(self, processorNss=prefixes)
result = Evaluate(query, context=ctx)
return result
xpath_attr_wrapper.xml_xpath = xml_xpath
def _namespaceURI(self):
try:
return self.xmlnsUri
except AttributeError:
return NULL_NAMESPACE
namespaceURI = property(_namespaceURI)
def _localName(self):
try:
return self.xmlnsLocalName
except AttributeError:
lname = self.nodeName
if lname[0] == '#': lname = None
return lname
localName = property(_localName)
def _prefix(self):
try:
return self.xmlnsPrefix
except AttributeError:
return NULL_PREFIX
prefix = property(_prefix)
def _parentNode(self):
try:
return self.xml_parent
except AttributeError:
return None
parentNode = property(_parentNode)
def _rootNode(self):
if self.parentNode:
return self.parentNode._rootNode()
return self
rootNode = property(_rootNode)
ownerDocument = rootNode
def _childNodes(self):
children = []
for node in self.xml_children:
if hasattr(node, 'next_elem'):
children.append(node)
elif isinstance(node, unicode):
children.append(text_wrapper(node, self))
elif getattr(node, 'nodeType', None) == Node.PROCESSING_INSTRUCTION_NODE:
children.append(node)
elif getattr(node, 'nodeType', None) == Node.COMMENT_NODE:
children.append(node)
else:
#Treat it as a text node bound to a Python type
children.append(unicode(node))
return children
childNodes = property(_childNodes)
def _xpathAttributes(self):
try:
attrs = self.xml_attributes
except AttributeError:
return []
return [ xpath_attr_wrapper(qname, ns, unicode(getattr(self, attr)), self)
for attr, (qname, ns) in self.xml_attributes.items() ]
xpathAttributes = property(_xpathAttributes)
def _attributes(self):
try:
attrs = self.xml_attributes
except AttributeError:
return {}
keys = [ (ns, SplitQName(qname))
for attr, (qname, ns) in self.xml_attributes.items() ]
values = [ xpath_attr_wrapper(qname, ns, unicode(getattr(self, attr)), self)
for attr, (qname, ns) in self.xml_attributes.items() ]
return dict(zip(keys, values))
attributes = property(_attributes)
def getAttributeNS(self, ns, local):
try:
attrs = self.xml_attributes
except AttributeError:
return {}
keys = [ (ns, SplitQName(qname)[1])
for attr, (qname, ns) in self.xml_attributes.items() ]
values = [ unicode(getattr(self, attr))
for attr, (qname, ns) in self.xml_attributes.items() ]
attr_dict = dict(zip(keys, values))
return attr_dict.get((ns, local), "")
@property
def docIndex(self):
#print "_docIndex", self.nodeType
ix = id(self)
return ix > 0 and ix or -ix
#docIndex = property(_docIndex)
def __cmp__(self, other):
if self is other: return 0
try:
return cmp(self.docIndex, other.docIndex)
except AttributeError:
return -cmp(other, unicode(self))
class BinderXpathException(Exception):
pass
NO_ATTRIBUTE_SUPPORT = _('You have attempted to use an XPath expression that requires attribute support in the binding. Try using the rule amara.binderytools.preserve_attribute_details.')
|