# -*- coding: utf-8 -*-
from lxml import etree

# Remove uppercase and whitespace
def sanitize(text):
    return unicode(text.lower(),'utf-8').translate({ord(' '): u'-'})

# Get classnames to be added to respective columns
# of each header cells, and add class attributes
# to the header cells
def process_header(table):
    header = table.find('.//thead')
    classnames = []
    for i, cell in enumerate(header.iter('th')):
        if cell.text != None:
            text = sanitize(cell.text)
        else:
            text = 'col-%d' % i
        classnames.append(text)
        cell.attrib['class'] = text
    return classnames

# Add class attribute classname to element, admitting
# conditional formatting as defined in special_classnames
def add_class_to_element(classname,element,special_classnames={}):
    if special_classnames.has_key(classname):
        try:
            text = element.text.lower()
        except AttributeError:
            print('cell contains no text, won\'t add case')
            element.attrib['class'] = classname
            return
        cases = special_classnames[classname]
        if cases.has_key(text):
            element.attrib['class'] = '%s %s-%s' % (classname, classname, cases[text])
        else:
            print('no case %s in %s, won\'t add case' % (text, classname))
            element.attrib['class'] = classname
            return
    else:
        element.attrib['class'] = classname
    return

# Populate table body with class attributes
def add_classes_to_table(table,classnames,special_classnames={}):
    for i, row in enumerate(table.iter('tr')):
        if i != 0 and i != 1:
            cells = row.findall('td')
            for j, cell in enumerate(cells):
                classname = classnames[j]
                add_class_to_element(classname,cell,special_classnames)
    return
            
# Define which content has special classes
mic_case = {
        'yes':'yes',
        'no' :'no'
        }
ping_case = {
        '<20' :'lt20'   ,
        '<40' :'lt40'   ,
        '<75' :'lt75'   ,
        '<100':'lt100',
        '>100':'gt100'
        }
special_classnames = {
        'microphone': mic_case,
        'ping'      : ping_case
        }

# Read table and add class attributes
dptable = etree.parse('dptable.html')
classnames = process_header(dptable)
add_classes_to_table(dptable,classnames,special_classnames)

# Insert table into main document
parser = etree.HTMLParser()
doc = etree.parse('outline.html', parser)
body = doc.find('.//body')
body.append(dptable.getroot())
doc.write('draft-packet.html', pretty_print = True, method = 'html', encoding = 'utf-8')

@@ -239,20 +239,16 @@
 r cells,
- and
  add cla
@@ -264,93 +264,209 @@
 utes
-%0A# to the header cells%0Adef process_header(table):%0A    header = table.find('.//thead')
+ and colspan%0A# where specified to the header cells. Since colspan%0A# creates new cells, we delete the corresponding%0A# number of cells to merge%0Adef process_header(table,merge=%7B%7D,delete=%7B%7D,no_rowspan=%7B%7D):
 %0A   
@@ -482,16 +482,35 @@
 es = %5B%5D%0A
+    to_remove = %5B%5D%0A
     for 
@@ -511,17 +511,16 @@
   for i,
- 
 cell in 
@@ -529,22 +529,21 @@
 umerate(
-header
+table
 .iter('t
@@ -544,24 +544,247 @@
 ter('th')):%0A
+        if len(to_remove):%0A            cell.getparent().remove(cell)%0A            to_remove.pop()%0A            text = 'col-%25d' %25 i%0A            classnames.append(text)%0A            cell.attrib%5B'class'%5D = text%0A        else:%0A    
         if c
@@ -801,16 +801,20 @@
 = None:%0A
+    
         
@@ -844,32 +844,36 @@
 l.text)%0A        
+    
 else:%0A          
@@ -866,32 +866,36 @@
 se:%0A            
+   
+ 
 text = 'col-%25d' 
@@ -890,32 +890,36 @@
  = 'col-%25d' %25 i%0A
+    
         classnam
@@ -946,35 +946,426 @@
     
-cell.attrib%5B'class'%5D = text
+    if text in delete:%0A                cell.getparent().remove(cell)%0A            else:%0A                cell.attrib%5B'class'%5D = text%0A                if text not in no_rowspan:%0A                    cell.attrib%5B'rowspan'%5D = '2'%0A                if text in merge:%0A                    colspan_val = merge%5Btext%5D%0A                    to_remove = range(int(colspan_val)-1)%0A                    cell.attrib%5B'colspan'%5D = colspan_val%0A
 %0A   
@@ -2376,67 +2376,63 @@
     
-if i != 0 and i != 1:%0A            cells = row.findall('td')
+cells = row.findall('td')%0A        if i != 0 and i != 1:
 %0A   
@@ -2587,16 +2587,323 @@
 snames)%0A
+        elif i == 1:%0A            for j, cell in enumerate(cells):%0A                classname = classnames%5Bj%5D%0A                if cell.text != None:%0A                    add_class_to_element('%25s %25s' %25 (classname,sanitize(cell.text)),cell)%0A                else:%0A                    cell.getparent().remove(cell)%0A
     retu
@@ -3269,16 +3269,153 @@
        %7D
+%0Amerge_cols = %7B%0A        'tagpro-name':'3',%0A        'location':'2',%0A        'ping':'2',%0A        %7D%0Ano_rowspan = %7B%0A        'ping',%0A        %7D
 %0A%0A# Read
@@ -3519,16 +3519,41 @@
 (dptable
+,merge_cols,%7B%7D,no_rowspan
 )%0Aadd_cl

add rowspan and colspan