This page demonstrates how to use an XSLT stylesheet to convert an XBEL (XML Bookmark Exchange Language) file into a structured, delimited text format. XBEL is a standard XML format used for storing and exchanging bookmarks between applications.

Overview

The provided XSLT stylesheet, transform.xsl, processes an XBEL file (e.g., bookmarks.xbel) and outputs the bookmarks in a pipe-delimited text format. This format is useful for importing bookmarks into other applications or for further processing.

How It Works

The XSLT stylesheet recursively processes each folder and bookmark in the XBEL file, constructing the folder path and appending the bookmark title and URL.

Use Cases

  • Data Migration: Convert XBEL bookmarks for use in other applications.
  • Data Analysis: Process bookmark data for analysis or reporting.
  • Integration: Import bookmarks into custom applications or databases.

Generating the output

xsltproc –output bookmarks.txt transform.xsl bookmarks.xbel

Search|Brave|https://search.brave.com/
Search|Ecosia|https://www.ecosia.org/
Search|Startpage|https://www.startpage.com/en/
Search|Google|https://www.google.co.uk/
Sport/Golf/Golf Clubs|10 Best Iron Sets for Beginners|https://www.golfbidder.co.uk/guides-and-advice/the-clubhouse/best-beginner-iron-sets
Sport/Golf/Golf Clubs|TaylorMade M2 2019|https://www.golfbidder.co.uk/taylormade-m2-2019-iron-set
Sport/Golf/Golf Clubs|Mizuno JPX 919|https://www.golfbidder.co.uk/mizuno-jpx-919-hot-metal-iron-set
Sport/Golf/Golf Clubs|Used PING Drivers That Will Revolutionise Your Game.|https://www.golfclubs4cash.co.uk/collections/ping-drivers

A snippet from the bookmarks.xbel file is shown below.

<?xml version="1.0" encoding="UTF-8"?>
<xbel version="1.0">
  <folder id="1773">
    <title>Search</title>
    <bookmark href="https://search.brave.com/" id="1775">
      <title>Brave</title>
    </bookmark>
    <bookmark href="https://www.ecosia.org/" id="1776">
      <title>Ecosia</title>
    </bookmark>
    <bookmark href="https://www.startpage.com/en/" id="1777">
      <title>Startpage</title>
    </bookmark>
    <bookmark href="https://www.google.co.uk/" id="1778">
      <title>Google</title>
    </bookmark>
  </folder>
  <folder id="1449">
    <title>Sport</title>
    <folder id="1658">
      <title>Golf</title>
      <folder id="1693">
        <title>Golf Clubs</title>
        <bookmark href="https://www.golfbidder.co.uk/guides-and-advice/the-clubhouse/best-beginner-iron-sets" id="1690">
          <title>10 Best Iron Sets for Beginners</title>
        </bookmark>
        <bookmark href="https://www.golfbidder.co.uk/taylormade-m2-2019-iron-set" id="1691">
          <title>TaylorMade M2 2019</title>
        </bookmark>
        <bookmark href="https://www.golfbidder.co.uk/mizuno-jpx-919-hot-metal-iron-set" id="1692">
          <title>Mizuno JPX 919</title>
        </bookmark>
        <bookmark href="https://www.golfclubs4cash.co.uk/collections/ping-drivers" id="1696">
          <title>Used PING Drivers That Will Revolutionise Your Game.</title>
        </bookmark>
      </folder>
    </folder>
  </folder>
</xbel>

The transform.xsl stylesheet is shown below.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet exclude-result-prefixes="exsl" version="1.0" xmlns:exsl="http://exslt.org/common" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:strip-space elements="*"/>
    <xsl:preserve-space elements="value component operation-data password check-password"/>
    <xsl:output indent="yes" method="xml"/>

<xsl:template match="xbel">
    <xsl:apply-templates select="folder" />
</xsl:template>

<xsl:template match="folder">
    <xsl:param name="folderName"/>
    <xsl:variable name="varFolderName" select="./title/text()" />
    <xsl:variable name="varLevel">
        <xsl:choose>
            <xsl:when test="string-length($folderName) > 0">
                <xsl:value-of select="concat($folderName, '/', $varFolderName)" />
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$varFolderName" />
            </xsl:otherwise>
        </xsl:choose>
    </xsl:variable>
    <xsl:for-each select="./bookmark">
        <xsl:variable name="varURL" select="./@href" />
        <xsl:variable name="varCurrent" select="." />
        <xsl:message>
            <xsl:value-of select="$varLevel" />
            <xsl:value-of select="'|'" />
            <xsl:value-of select="$varCurrent" />
            <xsl:value-of select="'|'" />
            <xsl:value-of select="$varURL" />
        </xsl:message>
    </xsl:for-each>
    <xsl:if test="folder">
        <xsl:apply-templates select="folder">
            <xsl:with-param name="folderName"><xsl:value-of select="$varLevel" /></xsl:with-param>
        </xsl:apply-templates>
    </xsl:if>
</xsl:template>

<xsl:template match="node()|@*">
    <xsl:apply-templates select="@*|node()"/>
</xsl:template>

</xsl:stylesheet>