Weblog Tomasza Przechlewskiego [Zdjęcie T. Przechlewskiego]


scrum
random image [Photo gallery]
Zestawienie tagów
1-wire | 18b20 | 1wire | 2140 | 3rz | adamowicz | afera | alsamixer | amazon | amber | amman | anniversary | antypis | apache | api | applebaum | arm | armenia | astronomy | asus | atom.xml | awk | aws | bachotek | bakłażan | balcerowicz | balta | banan | bash | batumi | berlin | białowieża | białystok | bibtex | bieszczady | birzeit | biznes | blogger | blogging | blosxom | bme280 | bono | borne-sulinowo | breugel | bt747 | budapeszt | budyniowo | budyń | bursztyn | campagnolo | canon | cedewu | chaos | chello | chiller | chillerpl | chown | christophe dominici | chujowetaśmy | ciasto | cmentarz | contour | coronavirus | covi19 | covid | covid19 | cron | css | csv | cukinia | curl | cycling | d54250wykh | darkages | dbi | debian | dejavu | dhcp | dht22 | dia | docbook | dom | dp1500 | ds18b20 | duda | dulkiewicz | dulkiewiczowa | dyndns | dynia | ebay | economy | ecowitt | ekonomia | elka | elm | emacs | emacs23 | english | ep | erasmus | erasmusplus | ess | eu | eurostat | excel | exif | exiftool | f11 | fc | fc11 | fc15 | fc29 | fc5 | fc8 | fedora | fedora21 | fenix | ffmpeg | finepix | firefox | flickr | folau | fontforge | fontspec | fonty | food | fop | forms | foto | france | francja | fripp | froggit | fuczki | fuji | fuse | gammu | garden | garmin | gas | gawk | gazwyb | gdańsk | gdynia | gender | geo | geocoding | georgia | gft | ggplot | ghost | git | github | gmail | gmaps | gnokii | gnus | google | google apps script | googlecl | googleearth | googlemaps | gotowanie | gphoto | gphoto2 | gps | gpsbabel | gpsphoto | gpx | gpx-viewer | greasemonkey | gruzja | grzyby | gus | gw1000 | haldaemon | handbrake | helsinki | hhi | historia | history | hitler | holocaust | holokaust | hp1000se | hpmini | humour | iblue747 | ical | iiyama | ikea | imagemagick | imap | inkscape | inne | internet | j10i2 | javascript | jhead | jifna | jordania | k800i | kajak | kamera | karob | kibbeh | kleinertest | kml | kmobiletools | knuth | kociewie kołem | kod | kolibki | komorowski | konwersja | krutynia | krynki | kuchnia | kurski | kłamstwo | latex | latex2rtf | latex3 | lcd | legend | lenny | lesund | lewactwo | lgbt-folly | liban | liberation | linksys | linux | lisp | lisrel | litwa | lizbona | logika | ltr | lubowla | lwp | lwów | m2wś | malta | mapquest | mapsource | maradona | marchew | marimekko | marvell | math | mathjax | mazury | mbank | mediolan | mencoder | mevo | mex | mh17 | michalak | michlmayr | microsoft | monitor | mp4box | mplayer | ms | msc | mssql | msw | mswindows | mtkbabel | museum | muzyka | mymaps | mysql | mz | nafisa | nanopi | natbib | navin | neapol | nekrolog | neo | neopi | netbook | niemcy | niemieckie zbrodnie | nikon | nmea | nowazelandia | nuc | nxml | oauth | oauth2 | obituary | ocr | odessa | okular | olympus | ooffice | ooxml | opera | osm | otf | otftotfm | other | ov5647 | overclocking | ozbekiston | padwa | palestyna | panoramio | paryż | pdf | pdfpages | pdftex | pdftk | pedophilia | perl | photo | photography | pi | picasa | picasaweb | pim | pine | pis | pit | pizero | plain | plotly | pls | plugin | po | podcast | podlasie | podróże | pogoda | politics | polityka | polsat | portugalia | postęp | powerpoint | połtawa | prelink | problem | propaganda | pseudointeligencja | pstoedit | putin | python | pywws | r | r1984 | radio | random | raspberry | raspberry pi | raspberrypi | raspbian | refugees | relaxng | ridley | router | rower | rowery | roztocze | rpi | rsync | rtf | ruby | rugby | rumunia | russia | rwc | rwc2007 | rwc2011 | rwc2019 | ryga | rzym | salerno | samba | sds011 | selenium | sem | senah | sernik | sheevaplug | sienkiewicz | signature | sikorski | sks | skype | skytraq | smoleńsk | sqlite | srtm | sshfs | ssl | staszek wawrykiewicz | statistcs | statistics | stats | statystyka | stix | stretch | supraśl | suwałki | svg | svn | swanetia | swornegacie | szwajcaria | słowacja | tallin | tbilisi | terrorism | tesseract | tex | texgyre | texlive | thunderbird | tomato | totalnaopozycja | tourism | tramp | trang | transylwania | truetype | trzaskowski | ttf | turcja | turkey | turystyka | tusk | tv | tv5monde | tweepy | twitter | tykocin | typetools | ubuntu | uchodźcy | udev | ue | ukraina | umap | unix | upc | updmap | ups | utf8 | uzbekistan | varia | video | vienna | virb edit | virbedit | vostro | wammu | wdc | wdfs | weather | weathercloud | webcam | webdav | webscrapping | weewx | wenecja | wh2080 | wiedeń | wikicommons | wilno | win10 | windows | windows8 | wine | wioślarstwo | wojna | word | wordpress | wrt54gl | ws1080 | wtyczka | wunderground | ww2 | www | wybory | wybory2015 | włochy | węgry | xemex | xetex | xft | xhtml | xine | xml | xmllint | xsd | xslt | xvidtune | youtube | yum | zaatar | zakopane | zakupy | zawodzie | zdf | zdrowie | zeropi | zgarden | zgony | zprojekt | łeba | łotwa | świdnica | żywność
Archiwum
06/2023 | 02/2023 | 01/2023 | 11/2022 | 10/2022 | 09/2022 | 07/2022 | 06/2022 | 04/2022 | 03/2022 | 02/2022 | 12/2021 | 09/2021 | 03/2021 | 01/2021 | 12/2020 | 11/2020 | 10/2020 | 09/2020 | 08/2020 | 07/2020 | 04/2020 | 03/2020 | 02/2020 | 01/2020 | 12/2019 | 11/2019 | 10/2019 | 09/2019 | 08/2019 | 07/2019 | 06/2019 | 04/2019 | 02/2019 | 01/2019 | 12/2018 | 11/2018 | 10/2018 | 09/2018 | 08/2018 | 07/2018 | 05/2018 | 04/2018 | 03/2018 | 02/2018 | 01/2018 | 11/2017 | 10/2017 | 09/2017 | 08/2017 | 07/2017 | 06/2017 | 05/2017 | 04/2017 | 03/2017 | 02/2017 | 01/2017 | 12/2016 | 11/2016 | 10/2016 | 09/2016 | 08/2016 | 06/2016 | 05/2016 | 04/2016 | 02/2016 | 12/2015 | 11/2015 | 09/2015 | 07/2015 | 06/2015 | 05/2015 | 02/2015 | 01/2015 | 12/2014 | 09/2014 | 07/2014 | 06/2014 | 04/2014 | 02/2014 | 01/2014 | 12/2013 | 11/2013 | 10/2013 | 09/2013 | 08/2013 | 07/2013 | 05/2013 | 04/2013 | 03/2013 | 02/2013 | 01/2013 | 12/2012 | 11/2012 | 10/2012 | 09/2012 | 08/2012 | 07/2012 | 05/2012 | 03/2012 | 02/2012 | 01/2012 | 12/2011 | 11/2011 | 10/2011 | 09/2011 | 08/2011 | 07/2011 | 06/2011 | 05/2011 | 04/2011 | 03/2011 | 02/2011 | 01/2011 | 12/2010 | 11/2010 | 10/2010 | 09/2010 | 08/2010 | 07/2010 | 06/2010 | 05/2010 | 04/2010 | 03/2010 | 02/2010 | 01/2010 | 12/2009 | 11/2009 | 10/2009 | 09/2009 | 08/2009 | 07/2009 | 06/2009 | 05/2009 | 04/2009 | 03/2009 | 02/2009 | 01/2009 | 12/2008 | 11/2008 | 10/2008 | 09/2008 | 08/2008 | 07/2008 | 06/2008 | 05/2008 | 04/2008 | 03/2008 | 02/2008 | 01/2008 | 12/2007 | 11/2007 | 10/2007 | 09/2007 | 08/2007 | 07/2007 |
O stronie
wykorzystywany jest blosxom plus następujące wtyczki: tagging, flatarchives, rss10, lastbuilddatexhtmlmime. Niektóre musiałem dopasować nieco do swoich potrzeb. Więcej o blosxom jest tutaj
Subskrypcja
RSS 1.0
Wysyłanie posta na blogger.com z wykorzystaniem Google API

GoogleCL przestało działać, bo Google przestało obsługiwać wersję OAuth 1.0. Ponadto, wygląda na to, że dostosowanie tego użytecznego narzędzia do wersji OAuth 2.0 bynajmniej nie jest trywialne na co wskazują liczne (ale do tej pory bezskuteczne) prośby i wołania o aktualizację GoogleCL, które można znaleźć w Internecie.

Ponieważ poszukiwania w miarę podobnego zamiennika zakończyły się niepowodzeniem, nie pozostało nic innego zmajstrować coś samodzielnie. Autoryzację OAuth 2.0 mam już opanową -- obsługuje ją Pythonowy skrypt oauth2picasa.py. (Skrypt jest (zapożyczonym) fragmentem z projektu picasawebsync). Wystarczyło dorobić następujący prosty skrypt Perlowy (por. także: Publishing a blog post):

#!/usr/bin/perl
# *** Wyslanie posta na blogger.com ***
use strict;
use LWP::UserAgent;
use XML::LibXML;
use Getopt::Long;

my $profileID="default";
my $blogID = '1928418645181504144'; # Identyfikator bloga
my $blog_entry ;

## Na wypadek gdy ktoś ma kilka blogów moża podać na któr
## ma być wysłany post używając opcji -blog
GetOptions( "blog=s" => \$blogID, "post=s" => \$blog_entry) ;

if ( $blog_entry eq '' ) {
print STDERR "*** USAGE: $0 -b blog -p message (-b is optional) ***\n" }

## sprawdź czy post jest well formed:
my $parser = XML::LibXML->new();
eval {my $res_  = $parser->parse_string($blog_entry) };
if ($@) { die "*** Error parsing post message! \n"; }

my $ACCESS_TOKEN=`oauth2blogger.py`; # pobierz ACCESS_TOKEN
print STDERR "*** AccessToken: $ACCESS_TOKEN ***\n";

my $req = HTTP::Request->new(
  POST => "https://www.blogger.com/feeds/$blogID/posts/default");

$req->header( 'Content-Type' => 'application/atom+xml' );
$req->header( 'Authorization' => "Bearer $ACCESS_TOKEN" );
$req->header( 'GData-Version' => '2' );

$req->content($blog_entry);

my $ua = LWP::UserAgent->new;
my $res = $ua->request($req);

# Jeżeli coś jest nie tak poniższe drukuje verbatim:
# http://www.perlmonks.org/bare/?node_id=464442
# $ua->prepare_request($req); print($req->as_string); exit ;

if ($res->is_success) {
   my $decoded_response = $res->decoded_content;
   print STDERR "*** OK *** $decoded_response\n"; }
else { die $res->status_line; }

Wykorzystanie:

perl blogger_upload.pl -p 'treść-posta'

Treść posta musi być oczywiście w formacie xHTML i zawierać się wewnątrz elementu content, który z kolei jest wewnątrz elementu entry. Element entry zawiera także title określający tytuł posta, oraz elementy category zawierające tagi. Przykładem może być coś takiego:

<entry xmlns='http://www.w3.org/2005/Atom'>
 <title type='text'>Marriage!</title>
 <content type='xhtml'>
    <div xmlns="http://www.w3.org/1999/xhtml">
      <p>Mr. Darcy has proposed marriage to me!</p>
      <p>He is the last man on earth I would ever desire to marry.</p>
      <p>Whatever shall I do?</p>
    </div>
  </content>
  <category scheme="http://www.blogger.com/atom/ns#" term="marriage" />
  <category scheme="http://www.blogger.com/atom/ns#" term="Mr. Darcy" />
</entry>

Opisany skrypt jest tutaj: blogger_upload.pl.

url | Wed, 08/07/2015 17:48 | tagi: , , , , ,
Konwersja z WordPressa do Bloggera

Kol. DM pisze sobie bloga używając WordPressa. Trochę go to kosztuje więc pojawiła się koncepcja żeby przeszedł na bezpłatnego Bloggera. Początkiem tej koncepcji jest oczywiście konwersja WP do formatu Bloggera.

Wpisy kol. DM zawierają tekst i dużo zdjęć oraz innych rysunków. Nie mam bladego pojęcia nt. WordPressa, ale dość szybko ustaliłem, że można wyeksportować treść posługując się stosowną funkcją dostępną z Kokpit→Narzędzia→Eksport (powstaje plik w formacie WordPress eXtended RSS -- WXR).

Plik WXR zapisujemy na dysku. Można go zamienić do formatu Bloggera korzystując z konwertera dostępnego tutaj. Jest wprawdzie napisane, że konwerter obsługuje pliki nie większe niż 1Mb, ale mój miał 4Mb i też poszło.

Plik kolegi DM zawiera tekst oraz prawidłowe linki do niektórych rysunków. Inne rysunki są wstawiane sprytnym czymś co nazywane jest shortcode (cf Shortcode API.) Nie wchodząc w szczegóły, zamiast rysunków w treści postu jest umieszczone np. coś takiego:

[nggallery id=506]

506 z kolei jest identyfikatorem zbioru rysunków, które fizycznie są przechowywane w katalogu:

wp-content/gallery

Każda galeria jest w oddzielnym katalogu, ale nazwami katalogów nie są identyfikatory typu 506 ale coś innego. Logując się do phpMyAdmin byłem w stanie ściągnąć całą bazę (w formacie SQL), w której siedzi WordPress. W jednej z tabel bazy znalazłem przypisanie id_galeriinazwa-katalogu-z-plikami

INSERT INTO `wp_ngg_gallery` (`gid`, `name`, `slug`, 
`path`, `title`, `galdesc`, `pageid`, `previewpic`, `author`) VALUES
(17, 'gottardo_2', '', 'wp-content/gallery/gottardo_2', '', '', 0, 0, 1),
(16, 'gottardo_1', '', 'wp-content/gallery/gottardo_1', '', '', 0, 0, 1),
(15, 'nufenen', '', 'wp-content/gallery/nufenen', NULL, NULL, 0, 0, 1),
... itd ...

Czyli zawartość czegoś, co w treści wygląda jak:

[nggallery id=15]

Znajduje się w katalogu wp-content/gallery/nufenen.

Teraz ściągnąłem cały katalog wp-content na dysk lokalny wykorzystując ncftp

ncftp -u USER -p PASS HOST
get -R -T wp-content

Następnie zamieniłem nazwy plików w następujący sposób:

nr_galerii__nazwa_pliku

Pliki wysłałem na google za pomocą skryptu. Istotne jest to, że skrypt po załadowaniu, zwraca URL zdjęcia pod którym jest ono dostępne na koncie googla:

100__fra_07063.jpg http://lh5.ggpht.com/-26SgLqsS1vM/UhdwT-Q62CI/AAAAAAAAABQ/k_ipaT4SNsE/100__fra_07063.jpg
100__fra_07064.jpg http://lh4.ggpht.com/-1kWivWwiZW4/UhdwU4vZWPI/AAAAAAAAABY/XxuIGrIPj8Q/100__fra_07064.jpg
itd...

Czyli zdjęcie 100__fra_07063.jpg (oryginalnie należące go galerii o identyfikatorze równym '100') jest dostępne pod adresem:

http://lh5.ggpht.com/-26SgLqsS1vM/UhdwT-Q62CI/AAAAAAAAABQ/k_ipaT4SNsE/100__fra_07063.jpg

Uwaga: Album ze zdjęciami na koncie googla może zawierać maksymalnie 1000 zdjęć. Jeżeli zdjęć jest więcej trzeba utworzyć więcej albumów.

Skryptem Perla (wyrażenia regularne/regułowe) zamieniam każde [nggallery id=506] na stosowny ekwiwalent. Przykładowo:

&lt;div id='gid_g509'&gt;
&lt;span&gt;&lt; a href="http://lh5.ggpht.com/-NZ_dEAq8qZI/Uhf_OPG9jiI/AAAAAAAADp8/BtBx9DwVgs4/509__1106_016.jpg" 
 imageanchor="1" style="margin-bottom: 1em; margin-right: .1em;"&gt;
&lt;img border="0" src="http://lh5.ggpht.com/-NZ_dEAq8qZI/Uhf_OPG9jiI/AAAAAAAADp8/BtBx9DwVgs4/s128/509__1106_016.jpg" 
  height='85' /&gt;&lt;/a&gt;
&lt;/span&gt;
 ... itd ...

Pozostałe zdjęcia mają `prawdziwe URLe' (a nie jakieś shortcody), ale oczywiście URLe te są złe bo wskazują na starego hosta. Zdjęcia te (z `prawdziwymi URLami') są przechowywane w katalogu ./wp-content/uploads. Ze zdjeciami postępuję, tak jak w przypadku zdjęć z galerii: 1) wysyłam na konto google skryptem; 2) zmieniam oryginalne URLe na URLe z konta google (skryptem Perla).

Przed importem do Bloggera warto sprawdzić czy plik, który ma być zaimportowany jest well-formed:

xmllint plik-do-zaimportowania.xml

url | Sat, 24/08/2013 21:57 | tagi: , ,
Problematyczny Lightbox w Bloggerze

Uwaga: w tym wpisie przykłady ilustrujące działanie Lightboksa NIE DZIAŁAJĄ, bo na blogu pinkaccordions.homelinux.org nie ma zainstalowanego Lightboksa. (Działają tutaj).

Kliknięcie zdjęcia lub obrazu zamieszczonego na blogu powoduje wyświetlenie go w nakładce na stronie. Jest to tzw. widok Lightbox. (cf. Widok Lightbox w Bloggerze):

<div>
<span>
<a href="https://lh4.googleusercontent.com/-cKBvbosMsII/Ua4zYPs99kI/AAAAAAAAB90/NLTG1cMbI88/epl313_6040342.jpg" 
 imageanchor="1" style="margin-bottom: 1em; margin-right: .1em;"><img border="0" 
 src="https://lh4.googleusercontent.com/-cKBvbosMsII/Ua4zYPs99kI/AAAAAAAAB90/NLTG1cMbI88/s128/epl313_6040342.jpg" /></a>
</span>
<span>
<a href="http://lh3.ggpht.com/-3POvL9Uv478/UhXICIpp_3I/AAAAAAAAB-w/K1rRrCU2D9c/epl313_6040338.jpg" 
 imageanchor="1" style="margin-bottom: 1em; margin-right: .1em;"><img border="0" 
 src="http://lh3.ggpht.com/-3POvL9Uv478/UhXICIpp_3I/AAAAAAAAB-w/K1rRrCU2D9c/s128/epl313_6040338.jpg" /></a>
</span>
<span>
<a href="http://lh6.ggpht.com/-nmAnV2_TD8U/UhXIIoYKraI/AAAAAAAAB-4/mWAJWpsOUZU/epl313_6040339.jpg" 
 imageanchor="1" style="margin-bottom: 1em; margin-right: .1em;"><img border="0" 
 src="http://lh6.ggpht.com/-nmAnV2_TD8U/UhXIIoYKraI/AAAAAAAAB-4/mWAJWpsOUZU/s128/epl313_6040339.jpg" /></a>
</span>
<span>
<a href="http://lh5.ggpht.com/-wO5_E5_jK14/UhXG7Rd-bSI/AAAAAAAAB-c/x76Ee7I9tgU/epl313_6040332.jpg" 
 imageanchor="1" style="margin-bottom: 1em; margin-right: .1em;"><img border="0" 
 src="http://lh5.ggpht.com/-wO5_E5_jK14/UhXG7Rd-bSI/AAAAAAAAB-c/x76Ee7I9tgU/s128/epl313_6040332.jpg" /></a>
</span>
</div>

Wynik jest następujący (kliknij w zdjęcie aby przejść do widoku Lightboksa):

W powyższym przykładzie zawartość atrybutów href i src jest prawie identyczna, bo różni się wyłącznie fragmentem s128/. Jest to przykład zastosowania sprytnego URLa, który spowoduje automagiczne przeskalowanie zdjęcia, tak aby dłuższy wymiar miał maksymalnie 128 pikseli. Jeżeli zamiast s128/ wstawimy s128-c/ albo s128-p/, to spowoduje to automagiczne wycięcie kwadratu o wymiarach maksymalnych 128 pikseli (crop). Przykład:

<div>
<span>
<a href="http://lh3.ggpht.com/.../epl313_6040338.jpg" 
 imageanchor="1" style="margin-bottom: 1em; margin-right: .1em;"><img border="0" 
 src="http://lh3.ggpht.com/.../s128-c/epl313_6040338.jpg" /></a>
</span>
<span>
<a href="http://lh3.ggpht.com/.../epl313_6040338.jpg" 
 imageanchor="1" style="margin-bottom: 1em; margin-right: .1em;"><img border="0" 
 src="http://lh3.ggpht.com/.../s128-p/epl313_6040338.jpg" /></a>
</span>

Symbolem ... oznaczono pominiętą część URLa (żeby nie wystawał na margines).

Wynik (kliknięcie w zdjęcie nie powoduje przejścia do widoku Lightboksa):

BTW: Liczba 128 nie jest magiczna, można przeskalować obrazek na inny wymiar.

Jeżeli zdjęcia są różnych wymiarów (portret/pejzaż), to s128-c/ (albo s128-p/) jest lepsze niż zwykłe s128, bo minaturki są jednakowej wielkości, tyle że Lightbox takie zdjęcia ignoruje. Czemu -- nie wiem... Nie wiem też jak to zmienić

Jako obejście problemu można przeskalować miniaturkę do jednakowej wysokości. Przykład:

<div>
<span>
<a href="https://lh4.googleusercontent.com/.../epl313_6040342.jpg" 
 imageanchor="1" style="margin-bottom: 1em;"><img border="0" height='85'
 src="https://lh4.googleusercontent.com/.../s128/epl313_6040342.jpg" /></a>
</span>
<span>
<a href="http://lh3.ggpht.com/.../epl313_6040338.jpg" 
 imageanchor="1" style="margin-bottom: 1em;"><img border="0" height='85'
 src="http://lh3.ggpht.com/.../s128/epl313_6040338.jpg" /></a>
</span>
<span>
<a href="http://lh6.ggpht.com/.../epl313_6040339.jpg" 
 imageanchor="1" style="margin-bottom: 1em;"><img border="0" height='85'
 src="http://lh6.ggpht.com/.../s128/epl313_6040339.jpg" /></a>
</span>
<span>
<a href="http://lh5.ggpht.com/.../epl313_6040332.jpg" 
 imageanchor="1" style="margin-bottom: 1em;"><img border="0" height='85'
 src="http://lh5.ggpht.com/.../s128/epl313_6040332.jpg" /></a>
</span>
</div>

Symbolem ... oznaczono pominiętą część URLa (żeby nie wystawał na margines).

Wynik jest następujący:

Kliknięcie w zdjęcie powoduje przejście do widoku Lightboksa.

Być może za czas jakiś problem zniknie. Wyświetlanie dla tego wpisu 10 zamiast 8 obrazków w widoku Lightboksa będzie tego dowodem:-)

url | Thu, 22/08/2013 11:47 | tagi: ,
How to import content from Blosxom to google Blogger

I have decided to give a try to Google Blogger service. I am an old dinosaur used to command line and tired with mouse and menus but as there is GoogleCL I am not scare. The problem is with my old posts---there is no way to post backdated blog entries with GoogleCL. A problem...

Fortunately there is export/import features on Blogger: one can backup blog content and/or upload it back to Google. In particular to import posts (and comments) into a blog, one have to click Import Blog from the blog's Settings. Next one have to select appropriate file and fill out the word verification beneath. The Blogger data format is Atom. So, to successfully import my old Blosxom entries I have to convert them to Atom.

I have made a few test entries and export them to check how the data looks like. Pretty wired but most of the content is irrelevant as it is concerned with formatting (css styles and such stuff is included). Also as I had comments disabled at my previous blog the problem is further simplified.

I have consulted Atom schema and tried with the following:

<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" 
      xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" 
      xmlns:georss="http://www.georss.org/georss" 
      xmlns:gd="http://schemas.google.com/g/2005" 
      xmlns:thr="http://purl.org/syndication/thread/1.0">';

<id>tag:blogger.com,1999:blog-1928418645181504144.archive</id>
<updated>2011-10-22T12:34:14.746-07:00</updated>
<title type='text'>pinkaccordions.blogspot.com</title>
<generator version='7.00' uri='http://www.blogger.com'>Blogger</generator>

The meaning of the elements should be obvious. The last element (generator) is required by Blogger import facility, otherwise error message is returned.

According to the schema inside feed element there is zero or more entry elements:

<entry>
<id>ID</id>
<published>DATE</published>
<updated>DATE</updated>
<category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/blogger/2008/kind#post"/>
  
<!-- tags, each as value of attribute `term' of element category -->
<category scheme='http://www.blogger.com/atom/ns#' term='tag1'/>
<category scheme='http://www.blogger.com/atom/ns#' term='tag2'/>
<title type='text'>title</title>
<content type='html'>post content ... </content>
</entry>

There is a final </feed> to guarantee that XML file is well formatted.

I have assumed the only important feature of id element is that it's content should be unique. I have decided to use MD5sum of the post content as IDs to guarantee that.

Finally, my old Blosxom-compatible entries looks similar to the example below:

<?xml version='1.0' encoding='iso-8859-2' ?>
<html xmlns="http://www.w3.org/1999/xhtml"><head>
<title>Przed finałami RWC 2011</title>
<!-- Tags: rwc2011,rugby,francja,polsat-->
</head><body><!-- ##Published : 2011-10-20T07:20:26CEST ##-->


<p>W RWC 2011 zostały już tylko dwa mecze: jutro (piątek), o trzecie miejsce oraz

So it was extremly easy to extract title, tags and publication date and format Atom-compliant XML file with the following Perl script:

#!/usr/bin/perl
# Variant of Blosxom to Blogger conversion
# 2011/10 t.przechlewski
#
use Digest::MD5 qw(md5_hex);

print '<?xml version="1.0" encoding="UTF-8"?>
<!-- id, title/updated jest wymagane w elementach feed/entry reszta opcjonalna -->
<!-- wyglada na minimalne oznakowanie -->
<feed xmlns="http://www.w3.org/2005/Atom" 
      xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" 
      xmlns:georss="http://www.georss.org/georss" 
      xmlns:gd="http://schemas.google.com/g/2005" 
      xmlns:thr="http://purl.org/syndication/thread/1.0">';

print "<id>tag:blogger.com,1999:blog-1928418645181504144.archive</id>";
print "<updated>2011-10-22T12:34:14.746-07:00</updated>";
print "<title type='text'>pinkaccordions.blogspot.com</title>";
print "<generator version='7.00' uri='http://www.blogger.com'>Blogger</generator>\n";

foreach $post_file (@ARGV) {

  my $post_title = $post_content = $md5sum = $published = '';
  my @post_kws = ();
  my $body = $in_pre  = 0;
  my $rel_URLs = 0;

  print STDERR "\n$post_file opened!\n";
  open POST, "$post_file" || die "*** cannot open $post_file ***\n";

  while (<POST>) {
    chomp();

    if (/<title>(.+)<\/title>/) {$post_title = $1 ; next ; }
    if (/<!--[ \t]*Tags:[ \t]*(.+)[ \t]*-->/) {$tags = $1 ; next ; }

    if (/<\/head><body>/) { 
      $body = 1 ; 
      ## </head><body><!-- ##Published : 2011-10-20T07:20:26CEST ##-->
      if (/##Published[ \t]+:[ \t]+([0-9T\-\:]+).+##/) { $published = $1; }
      print STDERR "Published: $published\n";
      next;
    }

    if (/<\/body><\/html>/) { $body = 0 ; next }

    if ( $body ) { 
      ## sprawdzam `przenosnosc URLi':
      if (/src[ \t]*=/) { 
	if (/pinkaccordions.homelinux.org/ || !(/http:\/\// ) ) { $rel_URLs = 1;  }
      }
      ## zawartość pre nie powinna być składana w jednym wierszu:
      if (/<pre>/)   { $in_pre = 1; $post_content .= "$_\n"; next ; }
      if (/<\/pre>/) { $in_pre = 0; $post_content .= "$_ "; next ; }
      if ( $in_pre ) { $post_content .= "$_\n"; }
      else {
	$post_content .= "$_ "; # ** musi być ze spacją **
      }
    }
  }

### ### ###

  if ($published eq '') { 
    warn "*** something wrong with: $post_file. Not published? Skipping....\n" ;
    close(POST);
    next ; 
  }
  if ( $tags eq '' || $post_title eq '' ) { 
    die "*** something wrong with: $post_file (tags: $tags/title: $post_title)\n"; }
  if ($rel_URLs) { die "*** suspicious relative URIs: $post_file\n"; }

  $post_content =~ s/\&/&amp;/g;
  $post_content =~ s/</&lt;/g;
  $post_content =~ s/>/&gt;/g;

  print STDERR "Title: $post_title Tags: $tags\n";

  @post_kws = split /,/, $tags;
  $md5sum = md5_hex($post_content);
  print STDERR "MD5sum: $md5sum\n";

  print "<entry>";
  print "<id>tag:blogger.com,1999:post-$md5sum</id>";
  print "<published>$published</published>";
  print "<updated>$published</updated>";
  print '<category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/blogger/2008/kind#post"/>';
  
  ## tags:
  foreach $k (@post_kws) { print "<category scheme='http://www.blogger.com/atom/ns#' term='$k'/>"; }

  print "<title type='text'>$post_title</title>";
  print "<content type='html'>$post_content</content></entry>";

  close(POST);

}

print "</feed>";

The minor problem was the default formatting of <pre>...</pre> which I use to show code snippets. I have to preserve line breaks (cf. $in_pre in the above Perl script) of pre element content as well as have to add the following to the default CSS styles (it is possible to modify CSS via Project →Template Designer →Advanced →Add CSS1)

pre { white-space:nowrap; font-size: 80%;  }

To convert simply run script as follows:

perl blogspot-import.pl post1 post2 post3.... > converted-posts.xml 

The above described script can be downloaded from here.

1In Polish: Projekt →Projektant szablonów →Advanced →Dodaj Arkusz CSS

url | Mon, 24/10/2011 18:50 | tagi: , , , , ,