2013-02-15 15 views
11

Sto provando a generare un'immagine PDF da un'immagine SVG utilizzando Python. Ho provato sia CairoSVG e svglib. Il problema è che in entrambi i casi i PDF generati non hanno nessuno degli stili CSS incorporati applicati.Conversione di SVG con CSS incorporato in PDF in Python

Ecco un semplice file in formato SVG, che dovrebbe rendere un rettangolo blu con un bordo nero:

<?xml version="1.0" standalone="no"?> 
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
    "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> 
<svg width="200" height="200" version="1.1" xmlns="http://www.w3.org/2000/svg"> 
    <defs> 
    <style type="text/css"><![CDATA[ 
     rect { 
     fill: #1f77b4; 
     stroke: black; 
     stroke-width: 1; 
     shape-rendering: crispEdges; 
     } 
    ]]></style> 
    </defs> 
    <rect x="50" y="50" width="100" height="100"></rect> 
</svg> 

Durante il rendering del PDF di questo file SVG usando CairoSVG, l'immagine PDF viene visualizzato come un rettangolo nero. Usando svglib, non vi è alcun tratto o stile applicato al rettangolo, quindi non è visibile. Qualcuno è a conoscenza di un modo per convertire un SVG con stili CSS in un'immagine PDF in Python?

+1

devo fare le miniature per le visualizzazioni D3, finora il migliore mi è venuta è una configurazione un po 'contorto utilizzando phantomjs per rendere il formato SVG. Poiché phantomjs è un vero browser webkit, SVG è reso esattamente come la versione del browser (c'è un modulo phantompy ma è segfaulting nel mio ambiente e non ho il tempo di indagare sul motivo). –

+3

La documentazione di CairoSVG ha questa nota: CairoSVG può usare lxml per analizzare il file SVG e tinycss più cssselect per applicare il CSS non incluso nell'attributo style dei tag. Se questi pacchetti non sono disponibili, i CSS saranno supportati solo negli attributi di stile. Se installi i pacchetti tinycss e cssselect, potrebbe risolvere il tuo problema. Vedi la sezione Dipendenze qui: http://cairosvg.org/user_documentation/ – MonkeyWrench

+0

@MonkeyWrench: è il miglior consiglio fino ad ora, se ti interessa puoi renderlo una risposta e raccogliere la taglia. –

risposta

8

(Con l'aiuto di @MonkeyWrench, dal momento che non inviare una risposta.)

Secondo il documentation,

CairoSVG può utilizzare lxml per analizzare il file in formato SVG, e tinycss più cssselect per applicare CSS non incluso nell'attributo style dei tag. Se questi pacchetti non sono disponibili, i CSS saranno supportati solo negli attributi di stile.

Per iniziare, ho installato tutte le dipendenze,

$ pip3 install cairosvg lxml tinycss cssselect 

Poi ho creato image.svg con il seguente contenuto:

<?xml version="1.0" standalone="no"?> 
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> 
<svg width="200" height="200" version="1.1" xmlns="http://www.w3.org/2000/svg"> 
    <defs> 
    <style type="text/css"><![CDATA[ 
     rect { 
     fill: #1f77b4; 
     stroke: black; 
     stroke-width: 1; 
     shape-rendering: crispEdges; 
     } 
    ]]></style> 
    </defs> 
    <rect x="50" y="50" width="100" height="100"></rect> 
</svg> 

Infine, ho eseguito cairosvg

$ cairosvg image.svg -o image.pdf 

E abbastanza sicuro, era un re blu ctangle.

blue

+1

Ha esempio, ha dato credito, tutto controlla. Bel lavoro, raccogli la tua taglia. :-) –

+1

Felice che ha funzionato. Sono stato via per un po '. Meglio stare al passo con il futuro. – MonkeyWrench

+0

Solo per capire meglio la soluzione: qual è il vantaggio di questo approccio rispetto all'uso di PhantomJS? – pir

1

Hai provato a utilizzare l'attributo di stile?

<svg xmlns="http://www.w3.org/2000/svg" version="1.1"> 
    <rect x="50" y="20" width="100" height="100" 
    style="fill:#1f77b4;stroke:black;stroke-width:1;shape-rendering: crispEdges;" 
    stroke-opacity:0.9"/> 
</svg> 

È in definitiva lo stesso di già, ma forse CairoSVG salta gli elementi di stile nel codice HTML.

+0

Questo markup viene reso correttamente sia da CairoSVG che da svglib. Tuttavia, sto provando a convertire le immagini SVG come renderizzate su una pagina web. Non è pratico applicare gli attributi di stile a ogni singolo elemento. Anche se questo non funzionerà per la mia situazione, questa è un'informazione utile. Quindi grazie! – jrothenbuhler

1

Suggerirei di utilizzare PhantomJS.

Fondamentalmente si tratta di un WebKit senza testa, guidato da Javascript.

Cerca nello script rasterize.js.

È possibile prendere le coordinate ed esportare (rasterizzare) quella sezione come un'immagine. Quindi è possibile utilizzare praticamente qualsiasi generatore di PDF, incorporando l'immagine. In alternativa, è possibile utilizzare un altro script per generare il file PDF con PhantomJS.

+0

'rasterize.js' può generare PDF, senza bisogno di generatori esterni. –