26 sys.path.append(os.path.dirname(__file__))
34 if sys.version_info[0] == 3:
38 _xml11_illegal_ranges = (
44 _xml10_illegal_ranges = _xml11_illegal_ranges + (
50 _xml_discouraged_ranges = (
55 if sys.maxunicode >= 0x10000:
57 _xml_discouraged_ranges = _xml_discouraged_ranges + (
73 (0x10fffe, 0x10ffff,),
77 def _range_seq_to_re(range_seq):
79 return re.compile(
u"[{}]".format(
81 u"{}-{}".format(re.escape(
unichr(lo)), re.escape(
unichr(hi)))
82 for lo, hi
in range_seq
86 _xml_filtered_chars_re = _range_seq_to_re(_xml10_illegal_ranges + _xml_discouraged_ranges)
88 def _handle_unrepresentable(data):
89 return _xml_filtered_chars_re.sub(
u"\ufffd", data)
101 def _escape(data, entities={}):
102 data = data.replace(
"&",
"&")
103 data = data.replace(
"<",
"<")
104 data = data.replace(
">",
">")
105 for chars, entity
in entities.items():
106 data = data.replace(chars, entity)
109 def _sanitize(data, entities={}):
110 return _escape(_handle_unrepresentable(data), entities=entities)
123 def _quoteattr(data, entities={}):
124 entities[
'\n']=
' ' 125 entities[
'\r']=
'' 126 data = _sanitize(data, entities)
129 data =
'"%s"' % data.replace(
'"',
""")
138 def _nssplit(qualifiedName):
139 fields = qualifiedName.split(
':', 1)
143 return (
None, fields[0])
145 def _nsassign(namespace):
146 return nsdict.setdefault(namespace,
"ns" + str(len(nsdict)))
162 previousSibling =
None 174 def _get_childNodes(self):
175 return self.childNodes
177 def _get_firstChild(self):
179 return self.childNodes[0]
181 def _get_lastChild(self):
183 return self.childNodes[-1]
190 if newChild.nodeType
not in self._child_node_types:
191 raise IllegalChild(
"%s cannot be child of %s" % (newChild.tagName, self.tagName))
192 if newChild.parentNode
is not None:
193 newChild.parentNode.removeChild(newChild)
198 index = self.childNodes.index(refChild)
200 raise xml.dom.NotFoundErr()
201 self.childNodes.insert(index, newChild)
202 newChild.nextSibling = refChild
203 refChild.previousSibling = newChild
205 node = self.childNodes[index-1]
206 node.nextSibling = newChild
207 newChild.previousSibling = node
209 newChild.previousSibling =
None 210 newChild.parentNode = self
218 if newChild.nodeType == self.DOCUMENT_FRAGMENT_NODE:
219 for c
in tuple(newChild.childNodes):
223 if newChild.nodeType
not in self._child_node_types:
224 raise IllegalChild(
"<%s> is not allowed in %s" % ( newChild.tagName, self.tagName))
225 if newChild.parentNode
is not None:
226 newChild.parentNode.removeChild(newChild)
227 _append_child(self, newChild)
228 newChild.nextSibling =
None 237 self.childNodes.remove(oldChild)
239 raise xml.dom.NotFoundErr()
240 if oldChild.nextSibling
is not None:
241 oldChild.nextSibling.previousSibling = oldChild.previousSibling
242 if oldChild.previousSibling
is not None:
243 oldChild.previousSibling.nextSibling = oldChild.nextSibling
244 oldChild.nextSibling = oldChild.previousSibling =
None 245 if self.ownerDocument:
246 self.ownerDocument.clear_caches()
247 oldChild.parentNode =
None 252 for c
in self.childNodes:
258 for c
in self.childNodes:
262 defproperty(Node,
"firstChild", doc=
"First child node, or None.")
263 defproperty(Node,
"lastChild", doc=
"Last child node, or None.")
265 def _append_child(self, node):
267 childNodes = self.childNodes
269 last = childNodes[-1]
270 node.__dict__[
"previousSibling"] = last
271 last.__dict__[
"nextSibling"] = node
272 childNodes.append(node)
273 node.__dict__[
"parentNode"] = self
282 childNodes = EmptyNodeList()
286 def _get_firstChild(self):
289 def _get_lastChild(self):
295 raise xml.dom.HierarchyRequestErr(
296 self.tagName +
" nodes cannot have children")
304 raise xml.dom.HierarchyRequestErr(
305 self.tagName +
" nodes do not have children")
310 raise xml.dom.NotFoundErr(
311 self.tagName +
" nodes do not have children")
316 raise xml.dom.HierarchyRequestErr(
317 self.tagName +
" nodes do not have children")
320 nodeType = Node.TEXT_NODE
339 nodeType = Node.CDATA_SECTION_NODE
348 f.write(
'<![CDATA[%s]]>' % self.
data.replace(
']]>',
']]>]]><![CDATA['))
359 nodeType = Node.ELEMENT_NODE
362 _child_node_types = (Node.ELEMENT_NODE,
363 Node.PROCESSING_INSTRUCTION_NODE,
366 Node.CDATA_SECTION_NODE,
367 Node.ENTITY_REFERENCE_NODE)
369 def __init__(self, attributes=None, text=None, cdata=None, qname=None, qattributes=None, check_grammar=True, **args):
370 if qname
is not None:
372 assert(hasattr(self,
'qname'))
380 if cdata
is not None:
384 if allowed_attrs
is not None:
385 allowed_args = [ a[1].lower().replace(
'-',
'')
for a
in allowed_attrs]
389 for attr, value
in attributes.items():
393 for attr, value
in qattributes.items():
395 if allowed_attrs
is not None:
397 for arg
in args.keys():
400 for arg
in args.keys():
402 if not check_grammar:
405 required = grammar.required_attributes.get(self.
qname)
409 raise AttributeError(
"Required attribute missing: %s in <%s>" % (r[1].lower().replace(
'-',
''), self.
tagName))
417 for ns,p
in nsdict.items():
418 if p == prefix:
return ns
426 if namespace
is None: namespace =
"" 427 prefix = _nsassign(namespace)
433 return grammar.allowed_attributes.get(self.
qname)
435 def _setOwnerDoc(self, element):
437 for child
in element.childNodes:
459 if check_grammar
and self.
qname not in grammar.allows_text:
470 if check_grammar
and self.
qname not in grammar.allows_text:
479 if allowed_attrs
is None:
480 if type(attr) == type(()):
481 prefix, localname = attr
484 raise AttributeError(
"Unable to add simple attribute - use (namespace, localpart)")
487 allowed_args = [ a[1].lower().replace(
'-',
'')
for a
in allowed_attrs]
488 if check_grammar
and attr
not in allowed_args:
489 raise AttributeError(
"Attribute %s is not allowed in <%s>" % ( attr, self.
tagName))
490 i = allowed_args.index(attr)
491 self.
removeAttrNS(allowed_attrs[i][0], allowed_attrs[i][1])
502 if attr ==
'parent' and value
is not None:
503 value.addElement(self)
506 if allowed_attrs
is None:
507 if type(attr) == type(()):
508 prefix, localname = attr
511 raise AttributeError(
"Unable to add simple attribute - use (namespace, localpart)")
514 allowed_args = [ a[1].lower().replace(
'-',
'')
for a
in allowed_attrs]
515 if check_grammar
and attr
not in allowed_args:
516 raise AttributeError(
"Attribute %s is not allowed in <%s>" % ( attr, self.
tagName))
517 i = allowed_args.index(attr)
518 self.
setAttrNS(allowed_attrs[i][0], allowed_attrs[i][1], value)
533 self.
attributes[(namespace, localpart)] = c.convert((namespace, localpart), value, self)
547 result = self.
attributes.get((namespace, localpart))
550 (type(namespace), type(namespace), type(namespace) == \
551 type(b
""), type(b
""), type(b
""))
or 552 (type(namespace), type(namespace), type(namespace) == \
553 type(
u""), type(
u""), type(
u""))
566 if allowed_attrs
is None:
567 if type(attr) == type(()):
568 prefix, localname = attr
571 raise AttributeError(
"Unable to get simple attribute - use (namespace, localpart)")
574 allowed_args = [ a[1].lower().replace(
'-',
'')
for a
in allowed_attrs]
575 i = allowed_args.index(attr)
576 return self.
getAttrNS(allowed_attrs[i][0], allowed_attrs[i][1])
581 for namespace, prefix
in self.
namespaces.items():
582 f.write(
u' xmlns:' + prefix +
u'="'+ _sanitize(str(namespace))+
'"')
585 f.write(
u' '+_sanitize(str(prefix+
u':'+qname[1]))+
u'='+_quoteattr(
unicode(self.
attributes[qname])))
600 for namespace, prefix
in self.
namespaces.items():
601 f.write(
u' xmlns:' + prefix +
u'="'+ _sanitize(str(namespace))+
u'"')
608 element.toXml(level+1,f)
609 f.write(
u'</'+self.
tagName+
'>')
613 def _getElementsByObj(self, obj, accumulator):
614 if self.
qname == obj.qname:
615 accumulator.append(self)
617 if e.nodeType == Node.ELEMENT_NODE:
618 accumulator = e._getElementsByObj(obj, accumulator)
624 obj = element(check_grammar=
False)
630 obj = element(check_grammar=
False)
631 return self.
qname == obj.qname
def setAttribute(self, attr, value, check_grammar=True)
Add an attribute to the element This is sort of a convenience method.
def toXml(self, level, f)
Generate an XML stream out of the tree structure.
def replaceChild(self, newChild, oldChild)
Raises an error.
def toXml(self, level, f)
Generate XML output of the node.
def addCDATA(self, cdata, check_grammar=True)
Adds CDATA to an element Setting check_grammar=False turns off grammar checking.
def get_knownns(self, prefix)
Odfpy maintains a list of known namespaces.
def removeAttribute(self, attr, check_grammar=True)
Removes an attribute by name.
def removeAttrNS(self, namespace, localpart)
def getAttribute(self, attr)
Get an attribute value.
super class for more specific nodes
def getAttrNS(self, namespace, localpart)
gets an attribute, given a namespace and a key
Complains if you add text or cdata to an element where it is not allowed.
def removeChild(self, oldChild)
Removes the child node indicated by oldChild from the list of children, and returns it...
def allowed_attributes(self)
def _setOwnerDoc(self, element)
def insertBefore(self, newChild, refChild)
Raises an error.
def getElementsByType(self, element)
Gets elements based on the type, which is function from text.py, draw.py etc.
def _getElementsByObj(self, obj, accumulator)
Complains if you add an element to a parent where it is not allowed.
def toXml(self, level, f)
Write XML in UTF-8.
Mixin that makes childless-ness easy to implement and avoids the complexity of the Node methods that ...
def __init__(self, attributes=None, text=None, cdata=None, qname=None, qattributes=None, check_grammar=True, args)
def setAttrNS(self, namespace, localpart, value)
Add an attribute to the element In case you need to add an attribute the library doesn't know about t...
def removeChild(self, oldChild)
Raises an error.
def addText(self, text, check_grammar=True)
Adds text to an element Setting check_grammar=False turns off grammar checking.
def write_open_tag(self, level, f)
def appendChild(self, node)
Raises an error.
Creates a arbitrary element and is intended to be subclassed not used on its own. ...
def isInstanceOf(self, element)
This is a check to see if the object is an instance of a type.
def write_close_tag(self, level, f)
def addElement(self, element, check_grammar=True)
adds an element to an Element
def appendChild(self, newChild)
Adds the node newChild to the end of the list of children of this node.
def get_nsprefix(self, namespace)
Odfpy maintains a list of known namespaces.
def insertBefore(self, newChild, refChild)
Inserts the node newChild before the existing child node refChild.
def hasChildNodes(self)
Tells whether this element has any children; text nodes, subelements, whatever.