5 import xml.parsers.expat
7 from optparse import OptionParser
9 ###############################################################################
13 ###############################################################################
16 def __init__( self, object, isElement ):
18 self.isElement = isElement
20 ###############################################################################
23 def __init__( self, parent, text=True, strip=True, delimBegin=None, delimEnd=None, newline=0 ):
27 self._delimBegin = delimBegin
28 self._delimEnd = delimEnd
29 self._newline = newline
32 def _addElement( self, child ):
33 self._stream.append( StreamEntry( child, True ))
35 def _addText( self, text ):
37 self._stream.append( StreamEntry( text, False ))
39 def _write( self, file ):
41 file.write( self._delimBegin )
42 for entry in self._stream:
44 entry.object.write( file )
46 file.write( str(entry.object) )
48 file.write( self._delimEnd )
50 def write( self, file ):
51 if self._newline > writer.newlineCount:
52 file.write( '\n' * (self._newline - writer.newlineCount))
55 ###############################################################################
57 class Document( Element ):
59 Element.__init__( self, None )
60 self._stack = [ self ]
63 self._debugIndent = ''
64 self._chapterLevel = 0
65 self._sectionLevel = 0
66 self._dividerCount = 0
67 self._majorHeading = Element( self, delimBegin='= ', delimEnd=' =\n\n' )
71 self._pending = self._stack[-1]
74 def _pushChild( self, child, add=True ):
76 self._pending._addElement( child );
77 self._stack.append( child )
81 def _chapterBegin( self ):
82 self._chapterLevel = self._chapterLevel + 1
84 def _chapterEnd( self ):
85 self._chapterLevel = self._chapterLevel - 1
87 def _sectionBegin( self ):
88 self._sectionLevel = self._sectionLevel + 1
90 def _sectionEnd( self ):
91 self._sectionLevel = self._sectionLevel - 1
93 def _write( self, file ):
95 file.write( "\n\n ===== `[`generated by xml2wiki on %s`]` =====" % (time.strftime( '%c' ) ))
96 Element._write( self, file )
99 def handleElementBegin( self, name, attrs ):
100 self._debugIndent = ' ' * (len(self._stack) - 1)
102 print( '%sBEGIN %s %s' % (self._debugIndent, name, attrs))
109 anchor = attrs['name']
111 e = Element( self._pending, delimBegin="'''", delimEnd="'''" )
112 elif name == 'chapter':
115 e = Element( self._pending, delimBegin='{{{{', delimEnd='}}}' )
116 elif name == 'command':
117 e = Element( self._pending, delimBegin='{{{', delimEnd='}}}' )
118 elif name == 'enumerate':
119 e = EnumerateElement( self._pending )
120 elif name == 'example':
121 e = CodeElement( self._pending )
123 e = Element( self._pending, delimBegin='{{{', delimEnd='}}}' )
125 e = Element( self._pending, delimBegin="''", delimEnd="''" )
126 elif name == 'itemize':
127 e = ItemizeElement( self._pending )
129 e = ItemElement( self._pending )
130 elif name == 'majorheading':
131 e = self._majorHeading
134 e = ParagraphElement( self._pending )
135 elif name == 'quotation':
136 e = IndentedElement( self._pending )
138 e = Element( self._pending, delimBegin='{{{', delimEnd='}}}' )
139 elif name == 'section' or name == 'subsection':
141 #elif name == 'table':
142 # e = Element( self._pending, newline=1, delimBegin='<table border="1" cellpadding="4">', delimEnd='</table>', strip=True )
143 elif name == 'tableitem':
144 e = TableItemElement( self._pending )
145 elif name == 'tableterm':
146 e = Element( self._pending, delimBegin=' ', delimEnd='::\n' )
147 elif name == 'title':
148 e = HeadingElement( self._pending, self._chapterLevel + self._sectionLevel )
149 elif name == 'unnumbered' or name == 'unnumberedsec':
152 e = UrefInline( self._pending )
153 elif name == 'urefdesc':
154 e = UrefDescInline( self._pending )
155 elif name == 'urefurl':
156 e = UrefUrlInline( self._pending )
158 e = XrefInline( self._pending )
159 elif name == 'xrefnodename':
160 e = XrefNodenameInline( self._pending )
163 self._pushChild( UnknownElement( self._pending ) )
164 if options.verbose > 2:
165 print( 'UNKNOWN:', name )
167 self._pushChild( e, add=shouldAdd )
169 def handleElementEnd( self, name ):
170 if name == 'chapter':
172 elif name == 'section' or name == 'subsection':
174 elif name == 'unnumbered' or name == 'unnumberedsec':
178 self._debugIndent = ' ' * (len(self._stack) - 1)
180 print( '%sEND %s' % (self._debugIndent, name))
182 def handleCharacterData( self, data ):
183 if options.verbose > 1:
184 print( '%s[%s]' % (self._debugIndent, data.strip()))
185 self._pending._addText( data )
187 ###############################################################################
189 class UnknownElement( Element ):
190 def __init__( self, parent ):
191 Element.__init__( self, parent, text=False )
193 ###############################################################################
195 class PragmaElement( Element ):
196 def __init__( self, parent, keyword ):
197 Element.__init__( self, parent, delimBegin=('#' + keyword + ' ') )
199 ###############################################################################
201 class BlockElement( Element ):
202 def __init__( self, parent ):
203 Element.__init__( self, parent, newline=2, text=False )
205 ###############################################################################
207 class CodeElement( Element ):
208 def __init__( self, parent ):
209 Element.__init__( self, parent, newline=2, delimBegin='{{{\n', delimEnd='\n}}}\n' )
211 ###############################################################################
213 class HeadingElement( Element ):
214 def __init__( self, parent, level ):
215 Element.__init__( self, parent, newline=2 )
217 self._anchor = anchor
220 self._delimBegin = ('=' * level) + ' '
221 self._delimEnd = ' %s #%s\n' % (('=' * level), self._anchor)
222 #self._delimEnd = ' ' + ('=' * level) + ' #%s\n' % (self._anchor)
224 # insert divider for level 1 headers
226 if options.toc or doc._dividerCount:
227 self._delimBegin = '----\n%s' % (self._delimBegin)
228 doc._dividerCount = doc._dividerCount + 1
232 ###############################################################################
234 class IndentedElement( BlockElement ):
235 def _write( self, file ):
237 Element._write( self, file )
240 ###############################################################################
242 class EnumerateElement( IndentedElement ):
245 ###############################################################################
247 class ItemizeElement( IndentedElement ):
250 ###############################################################################
252 class ItemElement( BlockElement ):
253 def __init__( self, parent ):
254 BlockElement.__init__( self, parent )
256 if isinstance( parent, TableItemElement ):
258 #self._delimBegin = '<td>'
259 #self._delimEnd = '</td>'
260 self._delimBegin = ' '
261 self._delimEnd = '\n'
263 ###############################################################################
265 class ParagraphElement( Element ):
266 def __init__( self, parent ):
267 Element.__init__( self, parent, newline=2 )
268 if isinstance( parent, ItemElement ):
269 if isinstance( parent._parent, TableItemElement ):
271 elif isinstance( parent._parent, EnumerateElement ):
273 self._delimBegin = '# '
276 self._delimBegin = '* '
278 ###############################################################################
280 class TableItemElement( Element ):
281 def __init__( self, parent ):
282 Element.__init__( self, parent, newline=1, text=False )
283 #self._delimBegin = '<tr>'
284 #self._delimEnd = '</tr>'
286 ###############################################################################
288 class UrefInline( Element ):
289 def __init__( self, parent ):
290 Element.__init__( self, parent, text=False, delimBegin='[', delimEnd=']' )
292 ###############################################################################
294 class UrefDescInline( Element ):
295 def __init__( self, parent ):
296 Element.__init__( self, parent, delimBegin=' ' )
298 ###############################################################################
300 class UrefUrlInline( Element ):
301 def __init__( self, parent ):
302 Element.__init__( self, parent )
304 ###############################################################################
306 class XrefInline( Element ):
307 def __init__( self, parent ):
308 Element.__init__( self, parent, text=False )
310 ###############################################################################
312 class XrefNodenameInline( Element ):
313 def __init__( self, parent ):
314 Element.__init__( self, parent )
316 def _write( self, file ):
317 buffer = io.StringIO()
318 Element._write( self, buffer )
319 name = str( buffer.getvalue() )
320 anchor = re.sub( ' ', '_', name )
321 file.write( '[#%s %s]' % (anchor, name) )
323 ###############################################################################
325 class IndentedWriter:
326 def __init__( self, size, file ):
327 self._chunk = ' ' * size
331 self._pending = False
333 self.newlineCount = 0
335 def decrease( self ):
336 self._level = self._level - 1
337 self._indent = self._chunk * self._level
339 def increase( self ):
340 self._level = self._level + 1
341 self._indent = self._chunk * self._level
343 def write( self, data ):
346 self._pending = False
347 self._file.write( self._indent )
349 self.newlineCount = self.newlineCount + 1
352 self.newlineCount = 0
353 self._file.write( b )
355 ###############################################################################
357 parser = OptionParser( 'Usage: %prog [OPTIONS] xml' )
358 parser.add_option( '-d', '--date', action='store_true', default=False, help='generate date-stamp under title' )
359 parser.add_option( '-t', '--toc', action='store_true', default=False, help='generate table of contents' )
360 parser.add_option( '-v', '--verbose', action='count', default=False, help='increase verbosity' )
362 (options, args) = parser.parse_args()
364 if( len(args) != 1 ):
365 parser.error( 'incorrect number of arguments' )
367 ###############################################################################
370 xml = xml.parsers.expat.ParserCreate()
372 xml.StartElementHandler = doc.handleElementBegin
373 xml.EndElementHandler = doc.handleElementEnd
374 xml.CharacterDataHandler = doc.handleCharacterData
378 with open( args[0], 'rb' ) as fin:
381 writer = IndentedWriter( 4, sys.stdout )
383 doc._majorHeading.write( writer )
386 writer.write( '%s* [#%s %s]\n' % (' ' * e._level,e._anchor,e._stream[0].object) )