26 sys.path.append(os.path.dirname(__file__))
29 from namespaces
import nsdict
31 from attrconverters
import AttrConverters
33 if sys.version_info.major == 3:
46 def _escape(data, entities={}):
47 data = data.replace(
"&",
"&")
48 data = data.replace(
"<",
"<")
49 data = data.replace(
">",
">")
50 for chars, entity
in entities.items():
51 data = data.replace(chars, entity)
65 def _quoteattr(data, entities={}):
66 entities[
'\n']=
' '
67 entities[
'\r']=
''
68 data = _escape(data, entities)
71 data =
'"%s"' % data.replace(
'"',
""")
80 def _nssplit(qualifiedName):
81 fields = qualifiedName.split(
':', 1)
85 return (
None, fields[0])
87 def _nsassign(namespace):
88 return nsdict.setdefault(namespace,
"ns" + str(len(nsdict)))
104 previousSibling =
None
116 def _get_childNodes(self):
117 return self.childNodes
119 def _get_firstChild(self):
121 return self.childNodes[0]
123 def _get_lastChild(self):
125 return self.childNodes[-1]
132 if newChild.nodeType
not in self._child_node_types:
133 raise IllegalChild(
"%s cannot be child of %s" % (newChild.tagName, self.tagName))
134 if newChild.parentNode
is not None:
135 newChild.parentNode.removeChild(newChild)
140 index = self.childNodes.index(refChild)
142 raise xml.dom.NotFoundErr()
143 self.childNodes.insert(index, newChild)
144 newChild.nextSibling = refChild
145 refChild.previousSibling = newChild
147 node = self.childNodes[index-1]
148 node.nextSibling = newChild
149 newChild.previousSibling = node
151 newChild.previousSibling =
None
152 newChild.parentNode = self
160 if newChild.nodeType == self.DOCUMENT_FRAGMENT_NODE:
161 for c
in tuple(newChild.childNodes):
165 if newChild.nodeType
not in self._child_node_types:
166 raise IllegalChild(
"<%s> is not allowed in %s" % ( newChild.tagName, self.tagName))
167 if newChild.parentNode
is not None:
168 newChild.parentNode.removeChild(newChild)
169 _append_child(self, newChild)
170 newChild.nextSibling =
None
179 self.childNodes.remove(oldChild)
181 raise xml.dom.NotFoundErr()
182 if oldChild.nextSibling
is not None:
183 oldChild.nextSibling.previousSibling = oldChild.previousSibling
184 if oldChild.previousSibling
is not None:
185 oldChild.previousSibling.nextSibling = oldChild.nextSibling
186 oldChild.nextSibling = oldChild.previousSibling =
None
187 if self.ownerDocument:
188 self.ownerDocument.clear_caches()
189 oldChild.parentNode =
None
194 for c
in self.childNodes:
200 for c
in self.childNodes:
204 defproperty(Node,
"firstChild", doc=
"First child node, or None.")
205 defproperty(Node,
"lastChild", doc=
"Last child node, or None.")
207 def _append_child(self, node):
209 childNodes = self.childNodes
211 last = childNodes[-1]
212 node.__dict__[
"previousSibling"] = last
213 last.__dict__[
"nextSibling"] = node
214 childNodes.append(node)
215 node.__dict__[
"parentNode"] = self
224 childNodes = EmptyNodeList()
228 def _get_firstChild(self):
231 def _get_lastChild(self):
237 raise xml.dom.HierarchyRequestErr(
238 self.tagName +
" nodes cannot have children")
246 raise xml.dom.HierarchyRequestErr(
247 self.tagName +
" nodes do not have children")
252 raise xml.dom.NotFoundErr(
253 self.tagName +
" nodes do not have children")
258 raise xml.dom.HierarchyRequestErr(
259 self.tagName +
" nodes do not have children")
262 nodeType = Node.TEXT_NODE
281 nodeType = Node.CDATA_SECTION_NODE
290 f.write(
'<![CDATA[%s]]>' % self.data.replace(
']]>',
']]>]]><![CDATA['))
301 nodeType = Node.ELEMENT_NODE
304 _child_node_types = (Node.ELEMENT_NODE,
305 Node.PROCESSING_INSTRUCTION_NODE,
308 Node.CDATA_SECTION_NODE,
309 Node.ENTITY_REFERENCE_NODE)
311 def __init__(self, attributes=None, text=None, cdata=None, qname=None, qattributes=None, check_grammar=True, **args):
312 if qname
is not None:
314 assert(hasattr(self,
'qname'))
322 if cdata
is not None:
326 if allowed_attrs
is not None:
327 allowed_args = [ a[1].lower().replace(
'-',
'')
for a
in allowed_attrs]
331 for attr, value
in attributes.items():
335 for attr, value
in qattributes.items():
337 if allowed_attrs
is not None:
339 for arg
in args.keys():
342 for arg
in args.keys():
344 if not check_grammar:
347 required = grammar.required_attributes.get(self.
qname)
351 raise AttributeError(
"Required attribute missing: %s in <%s>" % (r[1].lower().replace(
'-',
''), self.
tagName))
359 for ns,p
in nsdict.items():
360 if p == prefix:
return ns
368 if namespace
is None: namespace =
""
369 prefix = _nsassign(namespace)
375 return grammar.allowed_attributes.get(self.
qname)
377 def _setOwnerDoc(self, element):
379 for child
in element.childNodes:
394 self.ownerDocument.rebuild_caches(element)
401 if check_grammar
and self.
qname not in grammar.allows_text:
412 if check_grammar
and self.
qname not in grammar.allows_text:
421 if allowed_attrs
is None:
422 if type(attr) == type(()):
423 prefix, localname = attr
426 raise AttributeError(
"Unable to add simple attribute - use (namespace, localpart)")
429 allowed_args = [ a[1].lower().replace(
'-',
'')
for a
in allowed_attrs]
430 if check_grammar
and attr
not in allowed_args:
431 raise AttributeError(
"Attribute %s is not allowed in <%s>" % ( attr, self.
tagName))
432 i = allowed_args.index(attr)
433 self.
removeAttrNS(allowed_attrs[i][0], allowed_attrs[i][1])
445 if allowed_attrs
is None:
446 if type(attr) == type(()):
447 prefix, localname = attr
450 raise AttributeError(
"Unable to add simple attribute - use (namespace, localpart)")
453 allowed_args = [ a[1].lower().replace(
'-',
'')
for a
in allowed_attrs]
454 if check_grammar
and attr
not in allowed_args:
455 raise AttributeError(
"Attribute %s is not allowed in <%s>" % ( attr, self.
tagName))
456 i = allowed_args.index(attr)
457 self.
setAttrNS(allowed_attrs[i][0], allowed_attrs[i][1], value)
472 self.
attributes[(namespace, localpart)] = c.convert((namespace, localpart), value, self)
486 result = self.attributes.get((namespace, localpart))
489 (type(namespace), type(namespace), type(namespace) == \
490 type(b
""), type(b
""), type(b
""))
or
491 (type(namespace), type(namespace), type(namespace) == \
492 type(
u""), type(
u""), type(
u""))
505 if allowed_attrs
is None:
506 if type(attr) == type(()):
507 prefix, localname = attr
510 raise AttributeError(
"Unable to get simple attribute - use (namespace, localpart)")
513 allowed_args = [ a[1].lower().replace(
'-',
'')
for a
in allowed_attrs]
514 i = allowed_args.index(attr)
515 return self.
getAttrNS(allowed_attrs[i][0], allowed_attrs[i][1])
520 for namespace, prefix
in self.namespaces.items():
521 f.write(
u' xmlns:' + prefix +
u'="'+ _escape(str(namespace))+
'"')
522 for qname
in self.attributes.keys():
524 f.write(
u' '+_escape(str(prefix+
u':'+qname[1]))+
u'='+_quoteattr(
unicode(self.
attributes[qname])))
539 for namespace, prefix
in self.namespaces.items():
540 f.write(
u' xmlns:' + prefix +
u'="'+ _escape(str(namespace))+
u'"')
541 for qname
in self.attributes.keys():
547 element.toXml(level+1,f)
548 f.write(
u'</'+self.
tagName+
'>')
552 def _getElementsByObj(self, obj, accumulator):
553 if self.
qname == obj.qname:
554 accumulator.append(self)
556 if e.nodeType == Node.ELEMENT_NODE:
557 accumulator = e._getElementsByObj(obj, accumulator)
563 obj = element(check_grammar=
False)
569 obj = element(check_grammar=
False)
570 return self.
qname == obj.qname
def removeChild
Raises an error.
def toXml
Generate XML output of the node.
def get_nsprefix
Odfpy maintains a list of known namespaces.
super class for more specific nodes
def toXml
Write XML in UTF-8.
def addElement
adds an element to an Element
def isInstanceOf
This is a check to see if the object is an instance of a type.
def getAttribute
Get an attribute value.
def addText
Adds text to an element Setting check_grammar=False turns off grammar checking.
Complains if you add text or cdata to an element where it is not allowed.
def replaceChild
Raises an error.
def getAttrNS
gets an attribute, given a namespace and a key
Complains if you add an element to a parent where it is not allowed.
def removeAttribute
Removes an attribute by name.
Mixin that makes childless-ness easy to implement and avoids the complexity of the Node methods that ...
def appendChild
Adds the node newChild to the end of the list of children of this node.
def setAttribute
Add an attribute to the element This is sort of a convenience method.
def toXml
Generate an XML stream out of the tree structure.
def insertBefore
Inserts the node newChild before the existing child node refChild.
def insertBefore
Raises an error.
Creates a arbitrary element and is intended to be subclassed not used on its own. ...
def hasChildNodes
Tells whether this element has any children; text nodes, subelements, whatever.
def get_knownns
Odfpy maintains a list of known namespaces.
def getElementsByType
Gets elements based on the type, which is function from text.py, draw.py etc.
def addCDATA
Adds CDATA to an element Setting check_grammar=False turns off grammar checking.
def removeChild
Removes the child node indicated by oldChild from the list of children, and returns it...
def appendChild
Raises an error.
def setAttrNS
Add an attribute to the element In case you need to add an attribute the library doesn't know about t...