コード例 #1
0
ファイル: xelement.py プロジェクト: thatmattbone/betterxml
 def setAttributes(self, attrs=None):
     self.attrs = XAttributes(attrs)
コード例 #2
0
ファイル: xelement.py プロジェクト: thatmattbone/betterxml
class XElement:
    def __init__(self, name=None):
        self.children = []
        self.setAttributes()
        self.text = ""
        self.setName(name)

    def clone(self, nodes_visited={}):
        if nodes_visited.has_key(self):
            raise "circular reference in XElement.clone()"
        nodes_visited[self] = None
        my_class = self.__class__
        new_me = my_class()
        new_me.name = self.name
        new_me.text = self.text[:]
        new_me.attrs = XAttributes()
        for attr_name in self.attrs.keys():
            for attr_value in self.attrs[attr_name]:
                new_me.attrs[attr_name] = attr_value
        for c in self.children:
            c_clone = c.clone(nodes_visited)
            new_me.linkTo(c_clone)
        return new_me
    
    def setName(self, name):
        self.name = name

    def setAttributes(self, attrs=None):
        self.attrs = XAttributes(attrs)

    def setChildren(self, children):
        self.children = []
        for c in children:
            self.children.append(c)

    def hasAttributes(self, attr_list):
        return self.attrs.containsAttributes(attr_list)

    def getAttributes(self):
        return self.attrs

    def getAttribute(self, name, default_get=None):
        return self.attrs.getAttributeValue(name)

    def setText(self, text):
        self.text = text

    def initialize(self):
        pass

    def finalize(self, parent):
        pass

    def linkTo(self, element):
        if isinstance(element, XElement):
            self.children.append(element)
        else:
            raise "An XElement is required but %s was seen" % type(element)

    def cdata(self, text):
        self.text = self.text + text

    def printBFS(self, depth=0):
        print " " * depth, str(self)
        for node in self.children:
            node.printBFS(depth+1)

    def visit(self, depth):
        print " " * depth, str(self)

    def walkBFS(self, depth=0):
        self.doWalkBFS(depth)

    def doWalkBFS(self, depth=0):
        self.visit(depth)
        for node in self.children:
            node.doWalkBFS(depth+1)

    def getName(self):
        return self.name

    def getText(self):
        return self.text

    def getChildren(self, klass=None):
        if not klass:
            return self.children[:]

        children = []
        if type(klass) == type(''):
            for node in self.children:
                if node.__class__.__name__ == klass:
                    children.append(node)
        else:
            for node in self.children:
                if isinstance(node, klass):
                    children.append(node)
        return children

    def getChildrenByName(self, name):
        return [x for x in self.children if x.getName() == name]

    def getChild(self, klass=None, pos=0):
        children = self.getChildren(klass)
        try:
            return children[pos]
        except:
            return None

    def __str__(self):
        return self.toXML(indent_text="  ")
    
    __repr__ = __str__

    def toXML(self, **kw):
        """
        Convert an XElement tree into XML. You may pass:
           indent - a starting indentation level (integer); defaults to 0.
           indent_text - text to use for each level of indentation (string); 
              defaults to ' '
           prologue - a list of strings to emit as the prologue; defaults to
              ['<?xml ...?>','<!-- XIR Tools; (c) 2001, George K. THiruvathukal -->']
              This could be useful if you want to emit things like DTD and
              other stuff.
        """
        indent = kw.get('indent', 0)
        indent_text = kw.get('indent_text', ' ')

        repr = ''

        # Emit the prologue
        if not indent:
            prologue = kw.get('prologue', XELEMENT_PROLOGUE)
            for text in prologue:
                repr = repr + text + '\n'

        # Output the element header (indented)
        repr = repr + indent_text * indent
        repr = repr + '<%s' % (self.name)

        # And its attributes on the same line.
        if self.attrs:
            attrs_keys = self.attrs.getAttributes().keys()
            attrs_keys.sort()
            for attr_name in attrs_keys:
               attr_value = self.attrs.getAttributeValue(attr_name)
               repr = repr + ' %s="%s"' % (attr_name, attr_value)
        repr = repr + '>\n'

        # Output #PCDATA. Observe that my approach does *not* preserve data
        # between nested elements. This could be considered a feature.
        # NB: self.text *needs* to be escapeed. Get from saxutils.
        t = self.text
        t.strip()
        if t:
            repr = repr + (indent_text * (indent + 1)) + t + '\n'
        for node in self.children:
            repr = repr + node.toXML(indent=indent+1, indent_text=indent_text)

        # Output the closing element; make sure the last thing written 
        # emits a new line.
        repr = repr + indent_text * indent
        repr = repr + '</%s>' % (self.name) 
        repr = repr + '\n'
        return repr