2012-08-28 30 views
5

Tôi là một lập trình viên mới bắt đầu nên câu hỏi này có vẻ tầm thường: Tôi có một số tập tin văn bản có chứa có văn bản tab-delimited như:Chuyển đổi văn bản tab thành danh sách không có thứ tự html?

A 
    B 
    C 
     D 
     E 

Bây giờ tôi muốn tạo danh sách không có thứ tự .html ra điều này, với cấu trúc :

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

Ý tưởng của tôi là viết kịch bản Python, nhưng nếu có cách dễ dàng hơn (tự động) thì cũng tốt. Để xác định mức độ thụt đầu dòng và mục tên tôi sẽ cố gắng sử dụng mã này:

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] 

Trả lời

2

tokenize module hiểu định dạng nhập của bạn: các dòng chứa một số nhận dạng Python hợp lệ, mức thụt đầu dòng của các câu lệnh là đáng kể. ElementTree module cho phép bạn thao tác các cấu trúc cây trong bộ nhớ để nó có thể là flexable hơn để tách một tạo cây từ một render nó như 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 

Bất kỳ lớp cung cấp .start(), .end(), .data(), .close() phương pháp có thể được sử dụng như a TreeBuilder ví dụ: bạn chỉ có thể viết html trên bay thay vì xây dựng một cây.

Để phân tích stdin và viết html để thiết bị xuất chuẩn bạn có thể sử dụng ElementTree.write():

import sys 

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

Output:

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

Bạn có thể sử dụng bất kỳ tập tin, không chỉ sys.stdin/sys.stdout.

Lưu ý: Để ghi vào stdout trên Python 3, hãy sử dụng sys.stdout.buffer hoặc encoding="unicode" do sự phân biệt byte/Unicode.

0

Tôi nghĩ rằng các thuật toán đi như thế này:

  • theo dõi mức độ thụt đầu dòng hiện tại (bằng cách đếm số các tab trên mỗi dòng)

  • nếu sự gia tăng mức độ thụt đầu dòng: phát ra <ul> <li>current item</li>

  • nếu indentati vào mức độ giảm: phát ra <li>current item</li></ul>

  • nếu mức thụt đầu dòng vẫn giữ nguyên: phát ra <li>current item</li>

Đưa này vào mã là trái với các OP như tập thể dục

5

Hãy thử điều này (hoạt động trên thử nghiệm của bạn trường hợp):

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) 

Hope this helps

-1

Thuật toán rất đơn giản. Bạn lấy mức độ sâu của một dòng được chỉ báo bằng tab \ t và chuyển dấu đầu dòng tiếp theo sang phải \ t + \ t hoặc sang trái \ t \ t- \ t hoặc để nó ở cùng mức \ t.

Đảm bảo "in.txt" của bạn chứa các tab hoặc thay thế thụt lề bằng các tab nếu bạn sao chép từ đây. Nếu thụt lề được làm bằng khoảng trống, không có gì hoạt động. Và dấu phân tách là một dòng trống ở cuối. Bạn có thể thay đổi nó trong mã, nếu bạn muốn.

J.F. Giải pháp của Sebastian là tốt nhưng không xử lý unicode.

Tạo một tập tin văn bản "in.txt" trong mã UTF-8:

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

và chạy kịch bản "ul.py". Kịch bản lệnh sẽ tạo ra "out.html" và mở nó trong 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 sẽ là:

<!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> 
Các vấn đề liên quan