2012-08-28 11 views
5

soy un programador principiante así que esta pregunta podría parecer trivial: Tengo algunos archivos de texto containg texto delimitado por tabuladores como:¿Convertir texto tabulado a html lista desordenada?

A 
    B 
    C 
     D 
     E 

Ahora quiero generar listas no ordenadas .html fuera de este, con la estructura :

<ul> 
<li>A 
<ul><li>B</li> 
<li>C 
<ul><li>D</li> 
<li>E</li></ul></li></ul></li> 
</ul> 

Mi idea era escribir un script en Python, pero si hay una manera más fácil (automático), que está muy bien también. Para identificar el nombre de nivel de sangría y el tema me gustaría tratar de utilizar este código:

import sys 
indent = 0 
last = [] 
for line in sys.stdin: 
    count = 0 
    while line.startswith("\t"): 
     count += 1 
     line = line[1:] 
    if count > indent: 
     indent += 1 
     last.append(last[-1]) 
    elif count < indent: 
     indent -= 1 
     last = last[:-1] 

Respuesta

2

tokenize module entiende su formato de entrada: las líneas contienen un identificador de Python válido, el nivel de sangría de las declaraciones es significativo. ElementTree module le permite manipular las estructuras de árbol en memoria por lo que podría ser más flexable para separar una creación del árbol de una representación como html:

from tokenize import NAME, INDENT, DEDENT, ENDMARKER, NEWLINE, generate_tokens 
from xml.etree import ElementTree as etree 

def parse(file, TreeBuilder=etree.TreeBuilder): 
    tb = TreeBuilder() 
    tb.start('ul', {}) 
    for type_, text, start, end, line in generate_tokens(file.readline): 
     if type_ == NAME: # convert name to <li> item 
      tb.start('li', {}) 
      tb.data(text) 
      tb.end('li') 
     elif type_ == NEWLINE: 
      continue 
     elif type_ == INDENT: # start <ul> 
      tb.start('ul', {}) 
     elif type_ == DEDENT: # end </ul> 
      tb.end('ul') 
     elif type_ == ENDMARKER: # done 
      tb.end('ul') # end parent list 
      break 
     else: # unexpected token 
      assert 0, (type_, text, start, end, line) 
    return tb.close() # return root element 

Cualquier clase que proporciona .start(), .end(), .data(), .close() métodos se pueden utilizar como a TreeBuilder por ej., podría simplemente escribir html sobre la marcha en lugar de construir un árbol.

Para analizar la entrada estándar y escribir html en la salida estándar se puede utilizar ElementTree.write():

import sys 

etree.ElementTree(parse(sys.stdin)).write(sys.stdout, method='html') 

Salida:

<ul><li>A</li><ul><li>B</li><li>C</li><ul><li>D</li><li>E</li></ul></ul></ul> 

Se puede utilizar cualquier archivo, no sólo sys.stdin/sys.stdout.

Nota: Para escribir en stdout en Python 3 use sys.stdout.buffer o encoding="unicode" debido a la distinción bytes/Unicode.

0

Creo que el algoritmo es el siguiente:

  • no perder de vista el nivel de sangría actual (contando el número de lengüetas por línea)

  • si el aumento de nivel de sangría: emiten <ul> <li>current item</li>

  • si los indentati el nivel disminuye: emiten <li>current item</li></ul>

  • si el nivel de sangría sigue siendo el mismo: emiten <li>current item</li>

Su puesta en código se deja a la OP como el ejercicio

5

Prueba esto (funciona en su prueba caso):

import itertools 
def listify(filepath): 
    depth = 0 
    print "<ul>"*(depth+1) 
    for line in open(filepath): 
     line = line.rstrip() 
     newDepth = sum(1 for i in itertools.takewhile(lambda c: c=='\t', line)) 
     if newDepth > depth: 
      print "<ul>"*(newDepth-depth) 
     elif depth > newDepth: 
      print "</ul>"*(depth-newDepth) 
     print "<li>%s</li>" %(line.strip()) 
     depth = newDepth 
    print "</ul>"*(depth+1) 

espero que esto ayude

-1

El algoritmo es simple. Toma el nivel de profundidad de una línea que se indica con una tabulación \ t y desplaza la siguiente viñeta hacia la derecha \ t + \ t o hacia la izquierda \ t \ t- \ t o la deja en el mismo nivel \ t.

Asegúrate de que tu "in.txt" contiene pestañas o reemplaza la sangría con pestañas si la copias desde aquí. Si la sangría está hecha de espacios en blanco, nada funciona. Y el separador es una línea en blanco al final. Puede cambiarlo en el código, si lo desea.

J.F. La solución de Sebastian está bien pero no procesa unicode.

Crear un archivo de texto "in.txt" en la codificación UTF-8:

qqq 
    www 
    www 
     яяя 
     яяя 
    ыыы 
    ыыы 
qqq 
qqq 

y ejecutar el script "ul.py". El script creará el "out.html" y lo abrirá en Firefox.

#!/usr/bin/python 
# -*- coding: utf-8 -*- 

# The script exports a tabbed list from string into a HTML unordered list. 

import io, subprocess, sys 

f=io.open('in.txt', 'r', encoding='utf8') 
s=f.read() 
f.close() 

#--------------------------------------------- 

def ul(s): 

    L=s.split('\n\n') 

    s='<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">\n\ 
<html><head><meta content="text/html; charset=UTF-8" http-equiv="content-type"><title>List Out</title></head><body>' 

    for p in L: 
     e='' 
     if p.find('\t') != -1: 

      l=p.split('\n') 
      depth=0 
      e='<ul>' 
      i=0 

      for line in l: 
       if len(line) >0: 
        a=line.split('\t') 
        d=len(a)-1 

        if depth==d: 
         e=e+'<li>'+line+'</li>' 


        elif depth < d: 
         i=i+1 
         e=e+'<ul><li>'+line+'</li>' 
         depth=d 


        elif depth > d: 
         e=e+'</ul>'*(depth-d)+'<li>'+line+'</li>' 
         depth=d 
         i=depth 


      e=e+'</ul>'*i+'</ul>' 
      p=e.replace('\t','') 

      l=e.split('<ul>') 
      n1= len(l)-1 

      l=e.split('</ul>') 
      n2= len(l)-1 

      if n1 != n2: 
       msg='<div style="color: red;">Wrong bullets position.<br>&lt;ul&gt;: '+str(n1)+'<br>&lt;&frasl;ul&gt;: '+str(n2)+'<br> Correct your source.</div>' 
       p=p+msg 

     s=s+p+'\n\n' 

    return s 

#-------------------------------------  

def detach(cmd): 
    process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) 
    sys.exit() 

s=ul(s) 

f=io.open('out.html', 'w', encoding='utf8') 
s=f.write(s) 
f.close() 

cmd='firefox out.html' 
detach(cmd) 

HTML será:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> 
<html><head><meta content="text/html; charset=UTF-8" http-equiv="content-type"><title>List Out</title></head><body><ul><li>qqq</li><ul><li>www</li><li>www</li><ul><li>яяя</li><li>яяя</li></ul><li>ыыы</li><li>ыыы</li></ul><li>qqq</li><li>qqq</li></ul> 
Cuestiones relacionadas