2016-06-25 102 views
5

Voglio dividere il contenuto di un file CSS in blocchi di codice e inserire ogni blocco di codice in un elenco usando Python 3.5.Come posso dividere i blocchi di codice in un elenco?

Quindi, dato questo CSS:

h1 {color: #333, background-color: transparent} 
h2 { 
    font-weight:300 
} 
h3 
{ 
    font-weight: 200 
} 

possiamo dire chiaramente che esso ha più stili e/o tipi di indentazione significato della CSS deve essere riordinato per ottenere questo:

h1 { 
    color: #333,background-color: transparent; 
} 

h2 { 
    font-weight: 300; 
} 

h3 { 
    font-weight: 200; 
} 

Come posso usare Python per leggere una stringa ordinata di CSS e spingere ogni blocco di codice al suo interno in una lista Python come questa:

styles = [ 
    "h1 {\n color: #333,background-color: transparent;\n}", 
    "h2 {\n font-weight: 300;\n}", 
    "h3 {\n font-weight: 200;\n}" 
] 

Vorrei anche sottolineare che RegExp non è proprio il mio forte e non sono del tutto sicuro di cosa usare RegEx, ma stavo pensando che potrei usare RegExp [].split(...); insieme per raggiungere questo obiettivo.

Probabilmente utilizzare anche RegExp per eliminare la necessità di riordinare il foglio di stile prima di dividere i blocchi di codice.

NOTA: ho controllato questa domanda this ma sfortunatamente non è stato di aiuto.

+0

Eventuali duplicati di [Qual è il modo divinatorio per implementare un css parser/sostituto] (http://stackoverflow.com/questions/11592347/what-is-the-pythonic-way-to-implement-a-css-parser-replacer) – pvg

+0

@pvg No, sfortunatamente questo non ha risolto il mio problema. –

+0

@Mango Non è necessario implementare un parser da soli, è possibile utilizzare una piccola libreria. L'ho delineato nella mia risposta qui sotto. – oxalorg

risposta

3

Questa implementazione viene eseguita utilizzando tinycss, un semplice python puro css parser.

Questo funziona su disordinato css. Finché è legale.

import tinycss 
from collections import defaultdict 

parser = tinycss.make_parser('page3') 
# use parse_stylesheet_files to read from a file. 
stylesheet = parser.parse_stylesheet("""h1 {color: #333; background-color: transparent} 
     h2 { 
       font-weight:300 
     } 
     h3 
     { 
       font-weight: 200 
     } 
     h1{ 
     padding: 0px;} 
     """) 

# Initialize to empty list if key does not exists 
# This allows to group multiple blocks with same selectors 
temp = defaultdict(list) 

for rule in stylesheet.rules: 
    for dec in rule.declarations: 
     temp[rule.selector.as_css()].append((dec.name, dec.value.as_css())) 

print(temp) 

uscita:

defaultdict(<class 'list'>, 
      {'h1': [('color', '#333'), 
        ('background-color', 'transparent'), 
        ('padding', '0px')], 
      'h2': [('font-weight', '300')], 
      'h3': [('font-weight', '200')]}) 

vedere come i diversi h1 blocchi ricevuti bastonati in un unico elenco. Non sono estremamente consapevole delle complessità del CSS, ma è facile evitare che ciò accada.

Questo è molto più flessibile in quanto copre TUTTI casi limite, lavora con selettori, CSS2, CSS3 e, a differenza di una soluzione con le espressioni regolari.

Nota: ho inserito tutto in un dizionario, ma è possibile inserirlo facilmente come elenco. Fammi sapere se vuoi qualcosa con liste pure, ma dovrebbe essere relativamente banale se capisci cosa sto facendo.

+0

In quali casi una regex non viene coperta? Supponendo che il CSS sia sempre formattato correttamente, dovrebbe sempre funzionare https://repl.it/C5ws/7 –

+0

@JacobGray assumendo che sia formattato correttamente. E se non lo è, è comunque necessario un parser, quindi potrebbe anche avere un modo per risolverlo senza dover riordinare il css. – oxalorg

+0

L'OP sta chiedendo come dividere un pezzo di CSS * formattato *, quindi penso che sia sicuro assumere che l'input sia sempre formattato. Anche se l'input non è sempre formattato, puoi comunque dividerlo indipendentemente dalla formattazione da 're.compile (" (}) "). Split (css)'. Semplicemente non vedo alcun punto nell'usare una libreria per analizzare l'intero foglio di stile quando tutto ciò che vuoi è dividere ogni regola –

1

È possibile raggiungere questo obiettivo con un semplice file di lettura e sostituzione:

styles = [] 
with open('file.css') as file: 
    style = [] 
    for line in file.readlines(): 
     # If line is empty 
     if not line.strip(): 
      # If a block is non-empty 
      if style: 
       styles.append("".join(style)) 
       style = [] 
     else: 
      # Add to the current block 
      style.append(line) 
    styles.append("".join(style)) 

uscita:

>>> for s in styles: s 
h1 {\n color: #333,background-color: transparent;\n}\n 
h2 {\n font-weight: 300;\n}\n 
h3 {\n font-weight: 200;\n}\n 
+0

Questo codice si interromperà orribilmente anche se c'è una sola riga in bianco letteralmente OVUNQUE in tutto il foglio di stile css. – oxalorg

+0

@MiteshNinja Per "rottura orribile", presumo tu voglia dire che ci saranno linee vuote in 'styles' (se intendevi qualcos'altro, per favore chiarisci). Grazie per la segnalazione. Aggiustato. – th3an0maly

+0

Non penso che tu capisca. Il tuo codice ora si interromperà 'orribilmente' se c'è un singolo extra linea vuota presente OVUNQUE, tranne se la nuova riga è tra 2 blocchi. Se c'è una linea addizionale presente all'interno di un blocco, assumerà che il blocco sia finito e lo spinga su 'styles'. Si prega di ricontrollare il codice. – oxalorg