html.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. #!/usr/bin/env python3
  2. #
  3. # Simple XML to HTML converter.
  4. #
  5. # (C) 2005 Thomas Gleixner <tglx@linutronix.de>
  6. #
  7. # This program is free software; you can redistribute it and/or modify
  8. # it under the terms of the GNU General Public License version 2 as
  9. # published by the Free Software Foundation.
  10. #
  11. import sys
  12. import getopt
  13. import xml.sax
  14. import codecs
  15. if sys.version_info >= (3, 0):
  16. sys.stdout = codecs.getwriter("utf-8")(sys.stdout.detach())
  17. else:
  18. # reload() always needed because of https://docs.python.org/2.7/library/sys.html#sys.setdefaultencoding
  19. reload(sys)
  20. sys.setdefaultencoding('utf-8')
  21. sys.stdout = codecs.getwriter("utf-8")(sys.stdout)
  22. lookupdir = ''
  23. # Print the usage information
  24. def usage():
  25. print("USAGE:")
  26. print("html.py <-f -h file.xml>")
  27. print(" -d DIR use DIR as base directory for opening files")
  28. print(" -f write output to file.html (default is stdout)")
  29. print(" -h help")
  30. # Headerfields
  31. header = [
  32. "Mime-Version: 1.0\r\n",
  33. "Content-Type: text/plain; charset=utf-8\r\n",
  34. "Content-Transfer-Encoding: 8bit\r\n",
  35. "Content-Disposition: inline\r\n",
  36. ]
  37. html = []
  38. replace = []
  39. fdout = sys.stdout
  40. def replaceVars(line):
  41. cnt = 0
  42. while cnt < len(replace):
  43. # FIXME: this will match partial variable names, e.g. if XYZ and XYZ_ABC
  44. # are both in the replacement list, and XYZ appears first, it will
  45. # match and (partially) replace occurrences of XYZ_ABC.
  46. if line.find(replace[cnt]) >= 0:
  47. line = line.replace(replace[cnt], replace[cnt+1])
  48. cnt += 2
  49. return line
  50. def writeHtml(line):
  51. fdout.write(replaceVars(line))
  52. def startMenu(level):
  53. writeHtml("<div id=\"menu%s\">\n" % (level))
  54. def placeMenu(topic, link, mode):
  55. topic = replaceVars(topic)
  56. mode = replaceVars(mode)
  57. if mode == 'text':
  58. writeHtml("<p>%s</p>\n" % (topic))
  59. return
  60. if mode == 'selected':
  61. writeHtml("<span class=\"sel\">\n")
  62. else:
  63. writeHtml("<span class=\"nonsel\">\n")
  64. writeHtml("<a href=\"%s\"><span>%s</span></a>\n" % (link, topic))
  65. writeHtml("</span>\n")
  66. # configuration parser
  67. class docHandler(xml.sax.ContentHandler):
  68. def __init__(self):
  69. xml.sax.ContentHandler.__init__(self)
  70. self.content = ""
  71. def startElement(self, name, attrs):
  72. self.element = name
  73. if len(self.content) > 0:
  74. writeHtml(self.content)
  75. self.content = ""
  76. if name == "PAGE":
  77. return
  78. elif name == "INCLUDE":
  79. try:
  80. fd = codecs.open(attrs.get('file'), 'r', 'utf-8')
  81. except OSError:
  82. fd = codecs.open(lookupdir + attrs.get('file'), 'r', 'utf-8')
  83. lines = fd.readlines()
  84. fd.close()
  85. for line in lines:
  86. writeHtml(line)
  87. elif name == "PARSE":
  88. parseConfig(attrs.get('file'))
  89. elif name == 'STARTMENU':
  90. startMenu(attrs.get('level'))
  91. elif name == 'MENU':
  92. placeMenu(attrs.get('topic'), attrs.get('link'), attrs.get('mode'))
  93. elif name == 'ENDMENU':
  94. writeHtml("</div>\n")
  95. elif name == 'VAR':
  96. match = attrs.get('match')
  97. repl = attrs.get('replace')
  98. idx = len(replace)
  99. replace[idx:] = [match]
  100. idx = len(replace)
  101. replace[idx:] = [repl]
  102. else:
  103. writeHtml("<" + name)
  104. if attrs.getLength() > 0:
  105. names = attrs.getNames()
  106. for n in names:
  107. v = attrs.get(n)
  108. writeHtml(" " + n + "=\"" + v + "\"")
  109. writeHtml(" />" if name == "br" else ">")
  110. def characters(self, content):
  111. self.content += content
  112. def endElement(self, name):
  113. if name in {
  114. "PAGE", "INCLUDE", "PARSE", "STARTMENU", "ENDMENU", "MENU",
  115. "VAR", "br",
  116. }:
  117. return
  118. if len(self.content) > 0:
  119. writeHtml(self.content)
  120. self.content = ""
  121. writeHtml("</" + name + ">")
  122. # error handler
  123. class errHandler(xml.sax.ErrorHandler):
  124. def error(self, exception):
  125. sys.stderr.write("%s\n" % exception)
  126. def fatalError(self, exception):
  127. sys.stderr.write("Fatal error while parsing configuration\n")
  128. sys.stderr.write("%s\n" % exception)
  129. sys.exit(1)
  130. # parse the configuration file
  131. def parseConfig(file):
  132. # handlers
  133. dh = docHandler()
  134. eh = errHandler()
  135. # Create an XML parser
  136. parser = xml.sax.make_parser()
  137. # Set the handlers
  138. parser.setContentHandler(dh)
  139. parser.setErrorHandler(eh)
  140. try:
  141. fd = codecs.open(file, 'r', 'utf-8')
  142. except OSError:
  143. fd = codecs.open(lookupdir + file, 'r', 'utf-8')
  144. # Parse the file
  145. parser.parse(fd)
  146. fd.close()
  147. # Here we go
  148. # Parse the commandline
  149. writefile = 0
  150. try:
  151. (options, arguments) = getopt.getopt(sys.argv[1:], 'fhd:')
  152. except getopt.GetoptError as ex:
  153. print("ERROR:")
  154. print(ex.msg)
  155. usage()
  156. sys.exit(1)
  157. for option, value in options:
  158. if option == '-d':
  159. lookupdir = value + '/'
  160. if option == '-f':
  161. writefile = 1
  162. elif option == '-h':
  163. usage()
  164. sys.exit(0)
  165. # Handle special case VAR_ORIGIN
  166. idx = len(replace)
  167. replace[idx:] = ['VAR_ORIGIN']
  168. idx = len(replace)
  169. replace[idx:] = [lookupdir]
  170. if not arguments:
  171. print("No source file specified")
  172. usage()
  173. sys.exit(1)
  174. if writefile > 0:
  175. fname = arguments[0].split('.')[0]
  176. fname += ".html"
  177. fdout = codecs.open(fname, 'w', 'utf-8')
  178. parseConfig(arguments[0])
  179. if writefile > 0:
  180. fdout.close()