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 Fluendo, S.L. (www.fluendo.com). 
  6  # All rights reserved. 
  7   
  8  # This file may be distributed and/or modified under the terms of 
  9  # the GNU General Public License version 2 as published by 
 10  # the Free Software Foundation. 
 11  # This file is distributed without any warranty; without even the implied 
 12  # warranty of merchantability or fitness for a particular purpose. 
 13  # See "LICENSE.GPL" in the source distribution for more information. 
 14   
 15  # Licensees having purchased or holding a valid Flumotion Advanced 
 16  # Streaming Server license may use this file in accordance with the 
 17  # Flumotion Advanced Streaming Server Commercial License Agreement. 
 18  # See "LICENSE.Flumotion" in the source distribution for more information. 
 19   
 20  # Headers in this file shall remain intact. 
 21   
 22  """xml serializer and component comparison 
 23  """ 
 24   
 25  from cStringIO import StringIO 
 26  from xml.sax.saxutils import quoteattr 
 27   
 28  __version__ = "$Rev: 6964 $" 
 29   
 30   
31 -class XMLWriter(object):
32 - def __init__(self):
33 self._data = StringIO() 34 self._tagStack = [] 35 self._indent = 0 36 self._indentChar = ' ' 37 self._indentUnit = 2
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, line))
95
96 - def writeTag(self, tagName, attributes=None, data=None):
97 """Writes out and closes a tag. Optionally writes data as a child node. 98 @param tagName: name of the tag 99 @param attributes: attributes or None 100 @param data: data or None 101 """ 102 if attributes is None: 103 attributes = [] 104 prefix = '<%s' % (tagName,) 105 if data is not None: 106 suffix = '>%s</%s>' % (data, tagName) 107 else: 108 suffix = '/>' 109 attrs = self._collectAttributes( 110 attributes, len(prefix) + len(suffix)) 111 self.writeLine(prefix + attrs + suffix)
112
113 - def pushTag(self, tagName, attributes=None):
114 """Push a tag:: 115 - writes the tag and the attributes 116 - increase the indentation for subsequent calls 117 @param tagName: name of the tag to write 118 @type tagName: string 119 @param attributes: attributes to write 120 @type attributes: list of 2 sizes tuples; (name, value) 121 """ 122 self._openTag(tagName, attributes) 123 self._tagStack.append(tagName) 124 self._indent += self._indentUnit
125
126 - def popTag(self):
127 """Decreases the indentation and closes the previously opened tag. 128 @returns: name of the closed tag 129 """ 130 self._indent -= self._indentUnit 131 tagName = self._tagStack.pop() 132 self._closeTag(tagName) 133 return tagName
134 135
136 -def cmpComponentType(aType, bType):
137 """Compare two component types the way they should be written in an xml 138 file. Suitable for using as cmp argument to list.sort() or sorted(). 139 @param aType: first component type 140 @type aType: 141 @param bType: second component type 142 @type bType: 143 @returns: -1, 0 or 1, see L{__builtin__.cmp} 144 """ 145 for suffix in ['-producer', 146 '-converter', 147 '-encoder', 148 '-muxer', 149 '-streamer']: 150 bHasSuffix = bType.endswith(suffix) 151 if aType.endswith(suffix): 152 if bHasSuffix: 153 return cmp(aType, bType) 154 else: 155 return -1 156 elif bHasSuffix: 157 return 1 158 return cmp(aType, bType)
159