File: binderyxpath.py

package info (click to toggle)
amara 1.2a2-1
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 796 kB
  • ctags: 876
  • sloc: python: 8,650; xml: 1,450; makefile: 8; sh: 4
file content (220 lines) | stat: -rw-r--r-- 6,555 bytes parent folder | download | duplicates (2)
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.')