Project

General

Profile

1
# XML DOM tree manipulation
2

    
3
from xml.dom import Node
4
import xml.dom.minidom
5

    
6
def name_of(node): return node.tagName.lower()
7

    
8
def get_id(node): return node.getAttribute('id')
9

    
10
def set_id(node, id_): node.setAttribute('id', id_)
11

    
12
class NodeElemIter:
13
    def __init__(self, node): self.child = node.firstChild
14
    
15
    def __iter__(self): return self
16
    
17
    def curr(self):
18
        while self.child != None:
19
            if self.child.nodeType == Node.ELEMENT_NODE: return self.child
20
            self.child = self.child.nextSibling
21
        raise StopIteration
22
    
23
    def next(self):
24
        child = self.curr()
25
        self.child = self.child.nextSibling
26
        return child
27

    
28
def first_elem(node): return NodeElemIter(node).next()
29

    
30
class NodeElemReverseIter:
31
    def __init__(self, node): self.child = node.lastChild
32
    
33
    def __iter__(self): return self
34
    
35
    def curr(self):
36
        while self.child != None:
37
            if self.child.nodeType == Node.ELEMENT_NODE: return self.child
38
            self.child = self.child.previousSibling
39
        raise StopIteration
40
    
41
    def next(self):
42
        child = self.curr()
43
        self.child = self.child.previousSibling
44
        return child
45

    
46
def last_elem(node): return NodeElemReverseIter(node).next()
47

    
48
class NodeParentIter:
49
    def __init__(self, node): self.node = node
50
    
51
    def __iter__(self): return self
52
    
53
    def curr(self):
54
        if self.node != None and self.node.nodeType == Node.ELEMENT_NODE:
55
            return self.node
56
        raise StopIteration
57
    
58
    def next(self):
59
        node = self.curr()
60
        self.node = self.node.parentNode
61
        return node
62

    
63
def is_text(node):
64
    for child in NodeElemIter(node): return False # has an element node
65
    return True
66

    
67
def value(node):
68
    if node.firstChild != None: return node.firstChild.nodeValue
69
    else: return node.nodeValue
70

    
71
def set_value(doc, node, value):
72
    if node.nodeType == Node.ELEMENT_NODE:
73
        node.appendChild(doc.createTextNode(value))
74
    else: node.nodeValue = value
75

    
76
def by_tag_name(node, name, last_only=False):
77
    # last_only optimization returns last (most recently inserted) matching node
78
    children = []
79
    for child in NodeElemReverseIter(node):
80
        if child.tagName == name:
81
            children.append(child)
82
            if last_only: break
83
    return children
84

    
85
_writexml_orig = xml.dom.minidom.Element.writexml
86

    
87
def _writexml(self, writer, indent="", addindent="", newl=""):
88
    if self.firstChild != None and self.firstChild.nextSibling == None\
89
    and self.firstChild.nodeType == Node.TEXT_NODE: # a single text node
90
        writer.write(indent+'<'+self.tagName)
91
        for attr_idx in xrange(self.attributes.length):
92
            attr = self.attributes.item(attr_idx)
93
            writer.write(' '+attr.name+'='+attr.value)
94
        writer.write('>'+value(self)+'</'+self.tagName+'>'+newl)
95
    else: _writexml_orig(self, writer, indent, addindent, newl)
96

    
97
xml.dom.minidom.Element.writexml = _writexml
(7-7/9)