OSDN Git Service

BuildSystem:
[handbrake-jp/handbrake-jp-git.git] / doc / xml2wiki.py
1 import io
2 import re
3 import sys
4 import time
5 import xml.parsers.expat
6
7 from optparse import OptionParser
8
9 ###############################################################################
10
11 writer = None
12
13 ###############################################################################
14
15 class StreamEntry:
16     def __init__( self, object, isElement ):
17         self.object    = object
18         self.isElement = isElement
19     
20 ###############################################################################
21
22 class Element:
23     def __init__( self, parent, text=True, strip=True, delimBegin=None, delimEnd=None, newline=0 ):
24         self._parent     = parent
25         self._text       = text
26         self._strip      = strip
27         self._delimBegin = delimBegin
28         self._delimEnd   = delimEnd
29         self._newline    = newline
30         self._stream     = []
31
32     def _addElement( self, child ):
33         self._stream.append( StreamEntry( child, True ))
34
35     def _addText( self, text ):
36         if self._text:
37             self._stream.append( StreamEntry( text, False ))
38
39     def _write( self, file ):
40         if self._delimBegin:
41             file.write( self._delimBegin )
42         for entry in self._stream:
43             if entry.isElement:
44                 entry.object.write( file )
45             else:
46                 file.write( str(entry.object) )
47         if self._delimEnd:
48             file.write( self._delimEnd )
49
50     def write( self, file ):
51         if self._newline > writer.newlineCount:
52             file.write( '\n' * (self._newline - writer.newlineCount))
53         self._write( file )
54
55 ###############################################################################
56
57 class Document( Element ):
58     def __init__( self ):
59         Element.__init__( self, None )
60         self._stack        = [ self ]
61         self._pending      = self
62         self._summary      = None
63         self._debugIndent  = ''
64         self._chapterLevel = 0
65         self._sectionLevel = 0
66         self._dividerCount = 0
67
68         #self._pragmaSummary = PragmaElement( self, 'summary' )
69         #self._pragmaLabels = PragmaElement( self, 'labels' )
70         #self._pragmaLabels._addText( 'xml2wiki,Distribution,Featured' )
71
72     def _pop( self ):
73         self._stack.pop()
74         self._pending = self._stack[-1]
75         return self._pending
76
77     def _pushChild( self, child, add=True ):
78         if add:
79             self._pending._addElement( child );
80         self._stack.append( child )
81         self._pending = child
82         return self._pending
83
84     def _chapterBegin( self ):
85         self._chapterLevel = self._chapterLevel + 1
86
87     def _chapterEnd( self ):
88         self._chapterLevel = self._chapterLevel - 1
89
90     def _sectionBegin( self ):
91         self._sectionLevel = self._sectionLevel + 1
92
93     def _sectionEnd( self ):
94         self._sectionLevel = self._sectionLevel - 1
95
96     def _write( self, file ):
97         #self._pragmaSummary.write( file )
98         #file.write( '\n' )
99         #self._pragmaLabels.write( file )
100         if options.date:
101             file.write( "\n\n  ===== `[`generated by xml2wiki on %s`]` =====" % (time.strftime( '%c' ) ))
102         #if options.toc:
103         #    file.write( '\n\n<wiki:toc max_depth="3" />' )
104         Element._write( self, file )
105         file.write( '\n' )
106
107     def handleElementBegin( self, name, attrs ):
108         self._debugIndent = '    ' * (len(self._stack) - 1)
109         if options.verbose:
110             print( '%sBEGIN %s %s' % (self._debugIndent, name, attrs))
111
112         e = None
113         shouldAdd = True
114
115         if name == 'anchor':
116             global anchor
117             anchor = attrs['name']
118         elif name == 'b':
119             e = Element( self._pending, delimBegin="'''", delimEnd="'''" )
120         elif name == 'chapter':
121             self._chapterBegin()
122         elif name == 'code':
123             e = Element( self._pending, delimBegin='{{{{', delimEnd='}}}' )
124         elif name == 'command':
125             e = Element( self._pending, delimBegin='{{{', delimEnd='}}}' )
126         elif name == 'enumerate':
127             e = EnumerateElement( self._pending )
128         elif name == 'example':
129             e = CodeElement( self._pending )
130         elif name == 'file':
131             e = Element( self._pending, delimBegin='{{{', delimEnd='}}}' )
132         elif name == 'i':
133             e = Element( self._pending, delimBegin="''", delimEnd="''" )
134         elif name == 'itemize':
135             e = ItemizeElement( self._pending )
136         elif name == 'item':
137             e = ItemElement( self._pending )
138         #elif name == 'majorheading':
139         #    e = self._pragmaSummary
140         #    shouldAdd = False
141         elif name == 'para':
142             e = ParagraphElement( self._pending )
143         elif name == 'quotation':
144             e = IndentedElement( self._pending )
145         elif name == 'samp':
146             e = Element( self._pending, delimBegin='{{{', delimEnd='}}}' )
147         elif name == 'section' or name == 'subsection':
148             self._sectionBegin()
149         #elif name == 'table':
150         #    e = Element( self._pending, newline=1, delimBegin='<table border="1" cellpadding="4">', delimEnd='</table>', strip=True )
151         elif name == 'tableitem':
152             e = TableItemElement( self._pending )
153         elif name == 'tableterm':
154             e = Element( self._pending, delimBegin=' ', delimEnd='::\n' )
155         elif name == 'title':
156             e = HeadingElement( self._pending, self._chapterLevel + self._sectionLevel )
157         elif name == 'unnumbered' or name == 'unnumberedsec':
158             self._chapterBegin()
159         elif name == 'uref':
160             e = UrefInline( self._pending )
161         elif name == 'urefdesc':
162             e = UrefDescInline( self._pending )
163         elif name == 'urefurl':
164             e = UrefUrlInline( self._pending )
165         elif name == 'xref':
166             e = XrefInline( self._pending )
167         elif name == 'xrefnodename':
168             e = XrefNodenameInline( self._pending )
169
170         if not e:
171             self._pushChild( UnknownElement( self._pending ) )
172             if options.verbose > 2:
173                 print( 'UNKNOWN:', name )
174         else:
175             self._pushChild( e, add=shouldAdd )
176
177     def handleElementEnd( self, name ):
178         if name == 'chapter':
179             self._chapterEnd()
180         elif name == 'section' or name == 'subsection':
181             self._sectionEnd()
182         elif name == 'unnumbered' or name == 'unnumberedsec':
183             self._sectionEnd()
184
185         self._pop()
186         self._debugIndent = '    ' * (len(self._stack) - 1)
187         if options.verbose:
188             print( '%sEND %s' % (self._debugIndent, name))
189
190     def handleCharacterData( self, data ):
191         if options.verbose > 1:
192             print( '%s[%s]' % (self._debugIndent, data.strip()))
193         self._pending._addText( data )
194
195 ###############################################################################
196
197 class UnknownElement( Element ):
198     def __init__( self, parent ):
199         Element.__init__( self, parent, text=False )
200
201 ###############################################################################
202
203 class PragmaElement( Element ):
204     def __init__( self, parent, keyword ):
205         Element.__init__( self, parent, delimBegin=('#' + keyword + ' ') )
206
207 ###############################################################################
208
209 class BlockElement( Element ):
210     def __init__( self, parent ):
211         Element.__init__( self, parent, newline=2, text=False )
212
213 ###############################################################################
214
215 class CodeElement( Element ):
216     def __init__( self, parent ):
217         Element.__init__( self, parent, newline=2, delimBegin='{{{\n', delimEnd='\n}}}\n' )
218
219 ###############################################################################
220
221 class HeadingElement( Element ):
222     def __init__( self, parent, level ):
223         Element.__init__( self, parent, newline=2 )
224         global anchor
225         self._anchor = anchor
226
227         self._level = level
228         self._delimBegin = ('=' * level) + ' '
229         self._delimEnd   =  ' %s #%s\n' % (('=' * level), self._anchor)
230         #self._delimEnd   =  ' ' + ('=' * level) + ' #%s\n' % (self._anchor)
231
232         # insert divider for level 1 headers
233         if level == 1:
234             if options.toc or doc._dividerCount:
235                 self._delimBegin = '----\n%s' % (self._delimBegin)
236             doc._dividerCount = doc._dividerCount + 1
237
238         toc.append( self )
239
240 ###############################################################################
241
242 class IndentedElement( BlockElement ):
243     def _write( self, file ):
244         writer.increase()
245         Element._write( self, file )
246         writer.decrease()
247
248 ###############################################################################
249
250 class EnumerateElement( IndentedElement ):
251     pass
252
253 ###############################################################################
254
255 class ItemizeElement( IndentedElement ):
256     pass
257
258 ###############################################################################
259
260 class ItemElement( BlockElement ):
261     def __init__( self, parent ):
262         BlockElement.__init__( self, parent )
263         self._newline = 1
264         if isinstance( parent, TableItemElement ):
265             self._newline    = 0
266             #self._delimBegin = '<td>'
267             #self._delimEnd   = '</td>'
268             self._delimBegin = '    '
269             self._delimEnd   = '\n'
270
271 ###############################################################################
272
273 class ParagraphElement( Element ):
274     def __init__( self, parent ):
275         Element.__init__( self, parent, newline=2 )
276         if isinstance( parent, ItemElement ):
277             if isinstance( parent._parent, TableItemElement ):
278                 self._newline = 0
279             elif isinstance( parent._parent, EnumerateElement ):
280                 self._newline    = 1
281                 self._delimBegin = '# '
282             else:
283                 self._newline    = 1
284                 self._delimBegin = '* '
285
286 ###############################################################################
287
288 class TableItemElement( Element ):
289     def __init__( self, parent ):
290         Element.__init__( self, parent, newline=1, text=False )
291         #self._delimBegin = '<tr>'
292         #self._delimEnd   = '</tr>'
293
294 ###############################################################################
295
296 class UrefInline( Element ):
297     def __init__( self, parent ):
298         Element.__init__( self, parent, text=False, delimBegin='[', delimEnd=']' )
299
300 ###############################################################################
301
302 class UrefDescInline( Element ):
303     def __init__( self, parent ):
304         Element.__init__( self, parent, delimBegin=' ' )
305
306 ###############################################################################
307
308 class UrefUrlInline( Element ):
309     def __init__( self, parent ):
310         Element.__init__( self, parent )
311
312 ###############################################################################
313
314 class XrefInline( Element ):
315     def __init__( self, parent ):
316         Element.__init__( self, parent, text=False )
317
318 ###############################################################################
319
320 class XrefNodenameInline( Element ):
321     def __init__( self, parent ):
322         Element.__init__( self, parent )
323
324     def _write( self, file ):
325         buffer = io.StringIO()
326         Element._write( self, buffer )
327         name = str( buffer.getvalue() )
328         anchor = re.sub( ' ', '_', name )
329         file.write( '[#%s %s]' % (anchor, name) )
330
331 ###############################################################################
332
333 class IndentedWriter:
334     def __init__( self, size, file ):
335         self._chunk   = ' ' * size
336         self._file    = file
337         self._level   = 0
338         self._indent  = ''
339         self._pending = False
340
341         self.newlineCount = 0
342
343     def decrease( self ):
344         self._level  = self._level - 1
345         self._indent = self._chunk * self._level
346
347     def increase( self ):
348         self._level  = self._level + 1
349         self._indent = self._chunk * self._level
350
351     def write( self, data ):
352         for b in data:
353             if self._pending:
354                 self._pending = False
355                 self._file.write( self._indent )
356             if b == '\n':
357                 self.newlineCount = self.newlineCount + 1
358                 self._pending = True
359             else:
360                 self.newlineCount = 0
361             self._file.write( b )
362
363 ###############################################################################
364
365 parser = OptionParser( 'Usage: %prog [OPTIONS] xml' )
366 parser.add_option( '-d', '--date', action='store_true', default=False, help='generate date-stamp under title' )
367 parser.add_option( '-t', '--toc', action='store_true', default=False, help='generate table of contents' )
368 parser.add_option( '-v', '--verbose', action='count', default=False, help='increase verbosity' )
369
370 (options, args) = parser.parse_args()
371
372 if( len(args) != 1 ):
373     parser.error( 'incorrect number of arguments' )
374
375 ###############################################################################
376
377 doc = Document()
378 xml = xml.parsers.expat.ParserCreate()
379
380 xml.StartElementHandler  = doc.handleElementBegin
381 xml.EndElementHandler    = doc.handleElementEnd
382 xml.CharacterDataHandler = doc.handleCharacterData
383
384 anchor = None
385 toc = []
386 with open( args[0], 'rb' ) as fin:
387     xml.ParseFile( fin )
388
389 writer = IndentedWriter( 4, sys.stdout )
390
391 if options.toc:
392     for e in toc:
393         writer.write( '%s* [#%s %s]\n' % ('  ' * e._level,e._anchor,e._stream[0].object) )
394
395 doc.write( writer )