Skip to content

Instantly share code, notes, and snippets.

@Micronarrativ
Created June 9, 2014 11:35
Show Gist options
  • Save Micronarrativ/da0353fe51f0f42e96bb to your computer and use it in GitHub Desktop.
Save Micronarrativ/da0353fe51f0f42e96bb to your computer and use it in GitHub Desktop.
Converts KeepassX-XML export file to CSV file.
#!/usr/bin/ruby
# file: keepassx2csv.rb
#
# [*Description*]
# Exporting Password entries from a XML export of KeepassX to CSV
# The script will take care of the following fields:
# - Title
# - Username
# - Password
# - URL
# - Comment
#
# All other fields are ignored.
#
# [*Limitations*]
#
# Entries in the Category "Backup" are ignored and will not be exported.
# Blank lines in the comment field will not be preserved.
#
# [*Usage*]
#
# ~/
# |- keepassx.xml
# - keepassx2csv.rb
#
# Run:
# $ ./keepassx2csv.rb
#
require 'csv'
require 'rubygems'
require 'xmlsimple'
# Variables
inputFile = './keepassx.xml2'
outputFile = './keepassx.csv'
counter = 0
$csvArray = Array.new
# Read the data
data = XmlSimple.xml_in(inputFile)
# Loop the groups
data['group'].each do |group|
# Ignore entries in the backup category
# Those will confuse the output and create multiple entries
# if we do not deal with them
next if group['title'][0] == 'Backup'
# Now, create an array for each entry in the XML export
$category = group['title']
group['entry'].each do |groupEntry|
# Using the Ternary operator heavily
title = groupEntry['title'].is_a?(Array) ? groupEntry['title']: ''
username = groupEntry['username'].is_a?(Array) ? groupEntry['username']: ''
password = groupEntry['password'].is_a?(Array) ? groupEntry['password']: ''
url = groupEntry['url'].is_a?(Array) ? groupEntry['url'] : ''
groupEntry['comment'].each do |commentElement|
commentElement.class == Hash ? $comment = commentElement['content'] : $comment = [{}]
end
# Create an array with the gathered information and put it somewhere safe for later
$csvArray << [title,username,password,url,$category,$comment]
counter += 1
end
end
# Create the CSV output file
# Array elements with multiple fields (basically all comments)
# will contain a line-break string (\n) when merged into the CSV
CSV.open(outputFile, "wb", :quote_char => '"', :col_sep => ',' ) do |csv|
$csvArray.each do |entry|
title = entry[0][0].class == String ? entry[0][0] : ''
username = entry[1][0].class == String ? entry[1][0] : ''
password = entry[2][0].class == String ? entry[2][0] : ''
url = entry[3][0].class == String ? entry[3][0] : ''
category = entry[4][0].class == String ? entry[4][0] : ''
# Flatten the comments
entry[5].class == Array ? entry[5][0] != '{}' ? comments = entry[5].join("\n") : comments = '' : comments = ''
comments == '{}' ? comments = '': ''
# Output to CSV file
csv << [ "#{title}","#{username}", "#{password}", "#{url}","#{category}","#{comments}" ]
end
end
puts "Output file : #{outputFile}"
puts "Elements written: #{counter}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment