Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change

Opera Bookmarks to XBEL

by OeufMayo (Curate)
on Apr 24, 2001 at 00:31 UTC ( #74867=sourcecode: print w/replies, xml ) Need Help??
Category: Web Stuff
Author/Contact Info Briac 'Oeufmayo' Pilpré
Description: The python guys (they can't be all bad, after all :) have created a DTD called XML Bookmark Exchange Language which "is a rich interchange format for "bookmark" data as used by most Internet browsers." As I wanted to play with the XML::Writer module and clean up my bookmark files, I ended up whipping up this code. Have fun!

Update 2001-11-13: Complete rewrite of the adr2xbel script. It follows a bit more closely the python script found in the PyXML library demos.

#!/usr/bin/perl -w
use strict;
use XML::Writer;

# Small utility to parse Opera bookmark files.
# Originally written in Python by Lars Marius Garshol
# perl version - Briac Pilpré

my $version = <>;
die "Doesn't seem to be a Opera Hotlist\n" if $version !~ /^Opera/;

chomp( $version );

my $xml = new XML::Writer(DATA_MODE=>1, DATA_INDENT=>1);
       '+//IDN XML Bookmark Exchange Language 1.0//EN/
   $xml->dataElement('desc', $version);

while (<>){
        next unless /\S/;
        if ( $_ eq '#FOLDER' || $_ eq '#URL' ){
                my $node = $_;

                my $line;
                        local $/ = "";  # Paragraph mode
                        $line    = <>;

                if ($node eq '#FOLDER'){
                        my $name    = $1 if $line =~ /NAME=(.*)/;
                        my $created = $1 if $line =~ /CREATED=(.*)/;
                        $xml->dataElement('title', $name);

                elsif ($node eq '#URL') {
                        my $name    = $1 if $line =~ /NAME=(.*)/;
                        my $created = $1 if $line =~ /CREATED=(.*)/;
                        my $order   = $1 if $line =~ /ORDER=(.*)/;
                        my $visited = $1 if $line =~ /VISITED=(.*)/;
                        my $url     = $1 if $line =~ /URL=(.*)/;

                        $xml->startTag('bookmark', href => $url, 
                            added => $created, visited => $visited);
                        $xml->dataElement('title', $name);

        elsif ( $_ eq '-'){


Bonus: Added Bonus the xbel2adr script!

#!/usr/bin/perl -w
use strict;
use XML::Parser;
die "usage: $0 opera.xbel\n" if !$ARGV[0];
my $parser = new XML::Parser(Handlers => {
    Start=>\&start, End=>\&end, Char=>\&char,
my%equiv=(title=>'NAME', desc=>'DESCRIPTION');
my $flag = '';
sub char {
    my ($p, $txt) = @_; return if $txt =~ /^\s*$/;
    print $txt . "\n" if exists($equiv{$flag});
sub start {
    my ($p, $e, %a) = @_; $flag = $e;
    if    ($e eq 'folder'){  print "\n#FOLDER\n" }
    elsif ($e eq 'bookmark'){print "\n#URL\n\tURL=" . $a{'href'} if $a
    else  {print "\n\t" . $equiv{$e} . "=" if exists $equiv{$e}    }
sub end {undef $flag}

Previous version:

#!/usr/bin/perl -w
# adr2xbel : Convert Opera Bookmarks file to xbel
#            (XML Bookmark Exchange Language)
# OeufMayo - 23 apr 2001

use strict;
use XML::Writer;
use IO;
die "usage: $0 opera.adr\n" if !$ARGV[0];
my $output = new IO::File("> $ARGV[0].xbel.xml") or die $!;
my $writer = new XML::Writer(OUTPUT => $output, 
                             DATA_MODE => 1,
                     DATA_INDENT => 4) or die $!;
$writer->xmlDecl('iso-8859-1', 'no');
$writer->dataElement('title', 'Opera Hotlist version 2.0');

$/ = "";
while (<>){
    my @chunk = split(/\n\t/, $_);
    while ($chunk[0] =~ s/^(-\n)//){    # Folder end
        $writer->endTag('folder') if $chunk[0];

    if    ($chunk[0] =~ /^#FOLDER/){    # Folder beginning
        shift @chunk;
        my %attrs = &getAttlist(@chunk);
        for ('title', 'desc'){
            $writer->dataElement($_, $attrs{$_});
    elsif ($chunk[0] =~ /^#URL/){        # URL Tag
        shift @chunk;
        my %attrs = &getAttlist(@chunk);
                              'href' => $attrs{href} );
            for ('title', 'desc'){
                $writer->dataElement($_, $attrs{$_});



sub getAttlist {
    my %attrs;
    my %tr = (
    foreach $_ (@_){
        my ($key, $value) = ($1, $2);
        next unless (
                   $key eq 'URL'         || 
                   $key eq 'DESCRIPTION' || 
                   $key eq 'NAME'
        $key = $tr{$key};
        $attrs{$key} = $value;
    return %attrs;
Replies are listed 'Best First'.
Re: Opera Bookmarks to XBEL
by Anonymous Monk on Apr 25, 2003 at 16:53 UTC
    Cool stuff ! I am about to extend this, modifying to
    a) extract a complete subfolder of a huge opera bookmark file
    b) instead of opera adr to xbel I have changed into a docbook conforming
    XML document, which one can eg include as a chapter or so in a docbook documentation.
    The files are currently at
    Cheers, Marc Baaden (baaden at smplinux dot de)
      Me again .. just to say that the files have moved and are now at
      (some details available from
      Cheers, MB

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: sourcecode [id://74867]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (5)
As of 2023-01-31 08:00 GMT
Find Nodes?
    Voting Booth?

    No recent polls found