2013-02-15 11 views
11

Próbuję wygenerować obraz PDF z obrazu SVG za pomocą Pythona. Próbowałem zarówno CairoSVG i svglib. Problem polega na tym, że w obu przypadkach wygenerowane pliki PDF nie mają zastosowanych żadnych osadzonych stylów CSS.Konwersja SVG z osadzonym CSS na PDF w Pythonie

Oto prosty plik SVG, które powinny uczynić niebieski prostokąt z czarną obwódką:

<?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> 

Podczas renderowania PDF przy użyciu tego SVG CairoSVG obraz PDF jest wyświetlany w postaci czarnego prostokąta. Za pomocą svglib nie ma obrysu ani stylu zastosowanego do prostokąta, więc nie jest on widoczny. Czy ktoś jest świadomy sposobu konwersji SVG ze stylami CSS na obraz PDF w Pythonie?

+1

muszę zrobić miniatury wizualizacje D3, jak dotąd najlepszy wymyśliłem jest nieco zagmatwana konfiguracja za pomocą phantomjs do renderowania SVG. Ponieważ phantomjs jest prawdziwą przeglądarką Webkit, SVG jest renderowane dokładnie tak, jak wersja przeglądarki (istnieje moduł phantompy, ale jest to uszkodzenie w moim środowisku i brak mi czasu na zbadanie przyczyny). –

+3

Dokumentacja CairoSVG ma tę notatkę: CairoSVG może użyć lxml do parsowania pliku SVG, a tinycss plus cssselect do zastosowania CSS nie zawartego w atrybucie stylu tagów. Jeśli te pakiety nie są dostępne, CSS będzie obsługiwany tylko w atrybutach stylu. JEŚLI zainstalujesz pakiety tinycss i cssselect, może to rozwiązać twój problem. Zobacz sekcję Zależności tutaj: http://cairosvg.org/user_documentation/ – MonkeyWrench

+0

@MonkeyWrench: jest to najlepsza wskazówka do tej pory, jeśli zależy Ci na tym, możesz zrobić odpowiedź i zbierz nagrodę. –

Odpowiedz

8

(Z pomocą @MonkeyWrench, ponieważ nie pisać odpowiedzi.)

Według documentation,

CairoSVG mogą korzystać lxml do analizowania pliku SVG i tinycss plusa cssselect zastosować CSS nieuwzględnione w atrybucie stylu tagów. Jeśli te pakiety nie są dostępne, CSS będzie obsługiwany tylko w atrybutach stylu.

Aby zacząć, mam zainstalowane wszystkie zależności,

$ pip3 install cairosvg lxml tinycss cssselect 

Potem stworzył image.svg o następującej treści:

<?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> 

Wreszcie wykonany cairosvg

$ cairosvg image.svg -o image.pdf 

I rzeczywiście, był to niebieski re ctangle.

blue

+1

Ma przykład, dał kredyt, wszystko sprawdza. Dobra robota, zbieraj nagrodę. :-) –

+1

Cieszę się, że się udało. Nie było ich przez jakiś czas. Lepiej nadążyć w przyszłości. – MonkeyWrench

+0

Po prostu lepiej zrozumieć rozwiązanie - Jakie korzyści daje to podejście w porównaniu do korzystania z PhantomJS? – pir

1

Czy próbowałeś już użyć atrybutu stylu?

<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> 

Ostatecznie to samo, co już, ale może CairoSVG pomija elementy stylu w kodzie HTML.

+0

Ten znacznik jest poprawnie renderowany zarówno przez CairoSVG, jak i svglib. Próbuję jednak przekonwertować obrazy SVG w postaci renderowanej na stronie internetowej. Nie jest praktyczne stosowanie atrybutów stylu do każdego elementu. Chociaż to nie zadziała w mojej sytuacji, jest to przydatne informacje. Więc dziękuję! – jrothenbuhler

1

Proponuję użyć PhantomJS.

Zasadniczo jest to bezgłowy WebKit, obsługiwany przez Javascript.

Sprawdź w skrypcie rasterize.js.

Możesz pobrać współrzędne i wyeksportować (rasteryzować) tę sekcję jako obraz. Następnie możesz użyć praktycznie dowolnego generatora PDF, osadzając obraz. Alternatywnie można użyć innego skryptu do wygenerowania pliku PDF za pomocą PhantomJS.

+0

'rasterize.js' może generować pliki PDF, bez potrzeby generowania zewnętrznych generatorów. –