Package flumotion :: Package common :: Module xmlwriter
[hide private]

Source Code for Module flumotion.common.xmlwriter

  1  # -*- Mode: Python; -*- 
  2  # vi:si:et:sw=4:sts=4:ts=4 
  3   
  4  # Flumotion - a streaming media server 
  5  # Copyright (C) 2004,2005,2006,2007,2008,2009 Fluendo, S.L. 
  6  # Copyright (C) 2010,2011 Flumotion Services, S.A. 
  7  # All rights reserved. 
  8  # 
  9  # This file may be distributed and/or modified under the terms of 
 10  # the GNU Lesser General Public License version 2.1 as published by 
 11  # the Free Software Foundation. 
 12  # This file is distributed without any warranty; without even the implied 
 13  # warranty of merchantability or fitness for a particular purpose. 
 14  # See "LICENSE.LGPL" in the source distribution for more information. 
 15  # 
 16  # Headers in this file shall remain intact. 
 17   
 18  """xml serializer and component comparison 
 19  """ 
 20   
 21  from cStringIO import StringIO 
 22  from xml.sax.saxutils import quoteattr 
 23   
 24  __version__ = "$Rev$" 
 25   
 26   
27 -class XMLWriter(object):
28 29 encoding = '<?xml version="1.0" encoding="UTF-8"?>\n' 30
31 - def __init__(self):
32 self._data = StringIO() 33 self._tagStack = [] 34 self._indent = 0 35 self._indentChar = ' ' 36 self._indentUnit = 2 37 self._data.write(self.encoding)
38 39 # Private 40
41 - def _calcAttrsLength(self, attributes, indent):
42 if indent == -1: 43 return -1 44 attrLength = 0 45 for attr, value in attributes: 46 if value is None: 47 raise ValueError( 48 "value for attribute %s cannot be None" % (attr, )) 49 attrLength += 1 + len(attr) + len(quoteattr(value)) 50 return attrLength + indent
51
52 - def _collectAttributes(self, attributes, indent=-1):
53 if not attributes: 54 return '' 55 56 if self._calcAttrsLength(attributes, indent) > 79: 57 indentLen = self._indent + indent 58 else: 59 indentLen = 0 60 first = True 61 attrValue = '' 62 for attr, value in attributes: 63 if indentLen and not first: 64 attrValue += '\n%s' % (self._indentChar * indentLen) 65 if value is None: 66 raise ValueError( 67 "value for attribute %s cannot be None" % (attr, )) 68 attrValue += ' %s=%s' % (attr, quoteattr(value)) 69 if first: 70 first = False 71 return attrValue
72
73 - def _openTag(self, tagName, attributes=None):
74 attrs = self._collectAttributes( 75 attributes, len(tagName) + 1) 76 self.writeLine('<%s%s>' % (tagName, attrs))
77
78 - def _closeTag(self, tagName):
79 self.writeLine('</%s>' % (tagName, ))
80 81 # Public API 82
83 - def getXML(self):
84 """Fetches the xml written by the writer 85 @returns: the xml 86 @rtype: string 87 """ 88 return self._data.getvalue()
89
90 - def writeLine(self, line=''):
91 """Write a line to the xml. 92 This method honors the current indentation. 93 """ 94 self._data.write('%s%s\n' % (self._indentChar * self._indent, 95 line.encode('utf8')))
96
97 - def writeTag(self, tagName, attributes=None, data=None):
98 """Writes out and closes a tag. Optionally writes data as a child node. 99 @param tagName: name of the tag 100 @param attributes: attributes or None 101 @param data: data or None 102 """ 103 if attributes is None: 104 attributes = [] 105 prefix = '<%s' % (tagName, ) 106 if data is not None: 107 suffix = '>%s</%s>' % (data, tagName) 108 else: 109 suffix = '/>' 110 attrs = self._collectAttributes( 111 attributes, len(prefix) + len(suffix)) 112 self.writeLine(prefix + attrs + suffix)
113
114 - def pushTag(self, tagName, attributes=None):
115 """Push a tag:: 116 - writes the tag and the attributes 117 - increase the indentation for subsequent calls 118 @param tagName: name of the tag to write 119 @type tagName: string 120 @param attributes: attributes to write 121 @type attributes: list of 2 sizes tuples; (name, value) 122 """ 123 self._openTag(tagName, attributes) 124 self._tagStack.append(tagName) 125 self._indent += self._indentUnit
126
127 - def popTag(self):
128 """Decreases the indentation and closes the previously opened tag. 129 @returns: name of the closed tag 130 """ 131 self._indent -= self._indentUnit 132 tagName = self._tagStack.pop() 133 self._closeTag(tagName) 134 return tagName
135 136
137 -def cmpComponentType(aType, bType):
138 """Compare two component types the way they should be written in an xml 139 file. Suitable for using as cmp argument to list.sort() or sorted(). 140 @param aType: first component type 141 @type aType: 142 @param bType: second component type 143 @type bType: 144 @returns: -1, 0 or 1, see L{__builtin__.cmp} 145 """ 146 for suffix in ['-producer', 147 '-converter', 148 '-encoder', 149 '-muxer', 150 '-streamer']: 151 bHasSuffix = bType.endswith(suffix) 152 if aType.endswith(suffix): 153 if bHasSuffix: 154 return cmp(aType, bType) 155 else: 156 return -1 157 elif bHasSuffix: 158 return 1 159 return cmp(aType, bType)
160