utf8 → ascii

#!/usr/bin/env python
#
# html_utf8_to_ascii.py
# Copyright 2008 Hal Canary


import sys
fi = sys.stdin
fo = sys.stdout
#encoding = sys.stdin.encoding
encoding = 'UTF-8'

htmldict = {
  0x00a1: 'iexcl',
  0x00a2: 'cent',
  0x00a3: 'pound',
  0x00a4: 'curren',
  0x00a5: 'yen',
  0x00a6: 'brvbar',
  0x00a7: 'sect',
  0x00a8: 'uml',
  0x00a9: 'copy',
  0x00aa: 'ordf',
  0x00ab: 'laquo',
  0x00ac: 'not',
  0x00ad: 'shy',
  0x00ae: 'reg',
  0x00af: 'macr',
  0x00b0: 'deg',
  0x00b1: 'plusmn',
  0x00b2: 'sup2',
  0x00b3: 'sup3',
  0x00b4: 'acute',
  0x00b5: 'micro',
  0x00b6: 'para',
  0x00b7: 'middot',
  0x00b8: 'cedil',
  0x00b9: 'sup1',
  0x00ba: 'ordm',
  0x00bb: 'raquo',
  0x00bc: 'frac14',
  0x00bd: 'frac12',
  0x00be: 'frac34',
  0x00bf: 'iquest',
  0x00c0: 'Agrave',
  0x00c1: 'Aacute',
  0x00c2: 'Acirc',
  0x00c3: 'Atilde',
  0x00c4: 'Auml',
  0x00c5: 'Aring',
  0x00c6: 'AElig',
  0x00c7: 'Ccedil',
  0x00c8: 'Egrave',
  0x00c9: 'Eacute',
  0x00ca: 'Ecirc',
  0x00cb: 'Euml',
  0x00cc: 'Igrave',
  0x00cd: 'Iacute',
  0x00ce: 'Icirc',
  0x00cf: 'Iuml',
  0x00d0: 'ETH',
  0x00d1: 'Ntilde',
  0x00d2: 'Ograve',
  0x00d3: 'Oacute',
  0x00d4: 'Ocirc',
  0x00d5: 'Otilde',
  0x00d6: 'Ouml',
  0x00d7: 'times',
  0x00d8: 'Oslash',
  0x00d9: 'Ugrave',
  0x00da: 'Uacute',
  0x00db: 'Ucirc',
  0x00dc: 'Uuml',
  0x00dd: 'Yacute',
  0x00de: 'THORN',
  0x00df: 'szlig',
  0x00e0: 'agrave',
  0x00e1: 'aacute',
  0x00e2: 'acirc',
  0x00e3: 'atilde',
  0x00e4: 'auml',
  0x00e5: 'aring',
  0x00e6: 'aelig',
  0x00e7: 'ccedil',
  0x00e8: 'egrave',
  0x00e9: 'eacute',
  0x00ea: 'ecirc',
  0x00eb: 'euml',
  0x00ec: 'igrave',
  0x00ed: 'iacute',
  0x00ee: 'icirc',
  0x00ef: 'iuml',
  0x00f0: 'eth',
  0x00f1: 'ntilde',
  0x00f2: 'ograve',
  0x00f3: 'oacute',
  0x00f4: 'ocirc',
  0x00f5: 'otilde',
  0x00f6: 'ouml',
  0x00f7: 'divide',
  0x00f8: 'oslash',
  0x00f9: 'ugrave',
  0x00fa: 'uacute',
  0x00fb: 'ucirc',
  0x00fc: 'uuml',
  0x00fd: 'yacute',
  0x00fe: 'thorn',
  0x00ff: 'yuml',
  0x0152: 'OElig',
  0x0153: 'oelig',
  0x0160: 'Scaron',
  0x0161: 'scaron',
  0x0178: 'Yuml',
  0x0192: 'fnof',
  0x02c6: 'circ',
  0x02dc: 'tilde',
  0x0391: 'Alpha',
  0x0392: 'Beta',
  0x0393: 'Gamma',
  0x0394: 'Delta',
  0x0395: 'Epsilon',
  0x0396: 'Zeta',
  0x0397: 'Eta',
  0x0398: 'Theta',
  0x0399: 'Iota',
  0x039a: 'Kappa',
  0x039b: 'Lambda',
  0x039c: 'Mu',
  0x039d: 'Nu',
  0x039e: 'Xi',
  0x039f: 'Omicron',
  0x03a0: 'Pi',
  0x03a1: 'Rho',
  0x03a3: 'Sigma',
  0x03a4: 'Tau',
  0x03a5: 'Upsilon',
  0x03a6: 'Phi',
  0x03a7: 'Chi',
  0x03a8: 'Psi',
  0x03a9: 'Omega',
  0x03b1: 'alpha',
  0x03b2: 'beta',
  0x03b3: 'gamma',
  0x03b4: 'delta',
  0x03b5: 'epsilon',
  0x03b6: 'zeta',
  0x03b7: 'eta',
  0x03b8: 'theta',
  0x03b9: 'iota',
  0x03ba: 'kappa',
  0x03bb: 'lambda',
  0x03bc: 'mu',
  0x03bd: 'nu',
  0x03be: 'xi',
  0x03bf: 'omicron',
  0x03c0: 'pi',
  0x03c1: 'rho',
  0x03c2: 'sigmaf',
  0x03c3: 'sigma',
  0x03c4: 'tau',
  0x03c5: 'upsilon',
  0x03c6: 'phi',
  0x03c7: 'chi',
  0x03c8: 'psi',
  0x03c9: 'omega',
  0x03d1: 'thetasym',
  0x03d2: 'upsih',
  0x03d6: 'piv',
  0x2013: 'ndash',
  0x2014: 'mdash',
  0x2018: 'lsquo',
  0x2019: 'rsquo',
  0x201a: 'sbquo',
  0x201c: 'ldquo',
  0x201d: 'rdquo',
  0x201e: 'bdquo',
  0x2020: 'dagger',
  0x2021: 'Dagger',
  0x2022: 'bull',
  0x2026: 'hellip',
  0x2030: 'permil',
  0x2032: 'prime',
  0x2033: 'Prime',
  0x2039: 'lsaquo',
  0x203a: 'rsaquo',
  0x203e: 'oline',
  0x2044: 'frasl',
  0x20ac: 'euro',
  0x2111: 'image',
  0x2118: 'weierp',
  0x211c: 'real',
  0x2122: 'trade',
  0x2135: 'alefsym',
  0x2190: 'larr',
  0x2191: 'uarr',
  0x2192: 'rarr',
  0x2193: 'darr',
  0x2194: 'harr',
  0x21b5: 'crarr',
  0x21d0: 'lArr',
  0x21d1: 'uArr',
  0x21d2: 'rArr',
  0x21d3: 'dArr',
  0x21d4: 'hArr',
  0x2200: 'forall',
  0x2202: 'part',
  0x2203: 'exist',
  0x2205: 'empty',
  0x2207: 'nabla',
  0x2208: 'isin',
  0x2209: 'notin',
  0x220b: 'ni',
  0x220f: 'prod',
  0x2211: 'sum',
  0x2212: 'minus',
  0x2217: 'lowast',
  0x221a: 'radic',
  0x221d: 'prop',
  0x221e: 'infin',
  0x2220: 'ang',
  0x2227: 'and',
  0x2228: 'or',
  0x2229: 'cap',
  0x222a: 'cup',
  0x222b: 'int',
  0x2234: 'there4',
  0x223c: 'sim',
  0x2245: 'cong',
  0x2248: 'asymp',
  0x2260: 'ne',
  0x2261: 'equiv',
  0x2264: 'le',
  0x2265: 'ge',
  0x2282: 'sub',
  0x2283: 'sup',
  0x2284: 'nsub',
  0x2286: 'sube',
  0x2287: 'supe',
  0x2295: 'oplus',
  0x2297: 'otimes',
  0x22a5: 'perp',
  0x22c5: 'sdot',
  0x2308: 'lceil',
  0x2309: 'rceil',
  0x25ca: 'loz',
  0x2660: 'spades',
  0x2663: 'clubs',
  0x2665: 'hearts',
  0x2666: 'diams'
}

for line in fi:
  uline = unicode(line, encoding)
  for char in uline:
    ordchar = ord(char)
    if (ordchar >= 128):
      if htmldict.has_key(ordchar):
        fo.write("&%s;" % htmldict[ordchar])
      else:
        fo.write("&#x%04x;" % ordchar)
        #fo.write("&#%04d;" % ordchar)
    else:
      fo.write(chr(ord(char)))