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: 8738 $" 
 29   
 30   
31 -class XMLWriter(object):
32 33 encoding = '<?xml version="1.0" encoding="UTF-8"?>\n' 34
35 - def __init__(self):
36 self._data = StringIO() 37 self._tagStack = [] 38 self._indent = 0 39 self._indentChar = ' ' 40 self._indentUnit = 2 41 self._data.write(self.encoding)
42 43 # Private 44
45 - def _calcAttrsLength(self, attributes, indent):
46 if indent == -1: 47 return -1 48 attrLength = 0 49 for attr, value in attributes: 50 if value is None: 51 raise ValueError( 52 "value for attribute %s cannot be None" % (attr, )) 53 attrLength += 1 + len(attr) + len(quoteattr(value)) 54 return attrLength + indent
55
56 - def _collectAttributes(self, attributes, indent=-1):
57 if not attributes: 58 return '' 59 60 if self._calcAttrsLength(attributes, indent) > 79: 61 indentLen = self._indent + indent 62 else: 63 indentLen = 0 64 first = True 65 attrValue = '' 66 for attr, value in attributes: 67 if indentLen and not first: 68 attrValue += '\n%s' % (self._indentChar * indentLen) 69 if value is None: 70 raise ValueError( 71 "value for attribute %s cannot be None" % (attr, )) 72 attrValue += ' %s=%s' % (attr, quoteattr(value)) 73 if first: 74 first = False 75 return attrValue
76
77 - def _openTag(self, tagName, attributes=None):
78 attrs = self._collectAttributes( 79 attributes, len(tagName) + 1) 80 self.writeLine('<%s%s>' % (tagName, attrs))
81
82 - def _closeTag(self, tagName):
83 self.writeLine('</%s>' % (tagName, ))
84 85 # Public API 86
87 - def getXML(self):
88 """Fetches the xml written by the writer 89 @returns: the xml 90 @rtype: string 91 """ 92 return self._data.getvalue()
93
94 - def writeLine(self, line=''):
95 """Write a line to the xml. 96 This method honors the current indentation. 97 """ 98 self._data.write('%s%s\n' % (self._indentChar * self._indent, 99 line.encode('utf8')))
100
101 - def writeTag(self, tagName, attributes=None, data=None):
102 """Writes out and closes a tag. Optionally writes data as a child node. 103 @param tagName: name of the tag 104 @param attributes: attributes or None 105 @param data: data or None 106 """ 107 if attributes is None: 108 attributes = [] 109 prefix = '<%s' % (tagName, ) 110 if data is not None: 111 suffix = '>%s</%s>' % (data, tagName) 112 else: 113 suffix = '/>' 114 attrs = self._collectAttributes( 115 attributes, len(prefix) + len(suffix)) 116 self.writeLine(prefix + attrs + suffix)
117
118 - def pushTag(self, tagName, attributes=None):
119 """Push a tag:: 120 - writes the tag and the attributes 121 - increase the indentation for subsequent calls 122 @param tagName: name of the tag to write 123 @type tagName: string 124 @param attributes: attributes to write 125 @type attributes: list of 2 sizes tuples; (name, value) 126 """ 127 self._openTag(tagName, attributes) 128 self._tagStack.append(tagName) 129 self._indent += self._indentUnit
130
131 - def popTag(self):
132 """Decreases the indentation and closes the previously opened tag. 133 @returns: name of the closed tag 134 """ 135 self._indent -= self._indentUnit 136 tagName = self._tagStack.pop() 137 self._closeTag(tagName) 138 return tagName
139 140
141 -def cmpComponentType(aType, bType):
142 """Compare two component types the way they should be written in an xml 143 file. Suitable for using as cmp argument to list.sort() or sorted(). 144 @param aType: first component type 145 @type aType: 146 @param bType: second component type 147 @type bType: 148 @returns: -1, 0 or 1, see L{__builtin__.cmp} 149 """ 150 for suffix in ['-producer', 151 '-converter', 152 '-encoder', 153 '-muxer', 154 '-streamer']: 155 bHasSuffix = bType.endswith(suffix) 156 if aType.endswith(suffix): 157 if bHasSuffix: 158 return cmp(aType, bType) 159 else: 160 return -1 161 elif bHasSuffix: 162 return 1 163 return cmp(aType, bType)
164