First commit
This commit is contained in:
commit
adc2305713
|
@ -0,0 +1,3 @@
|
|||
__pycache__/
|
||||
test/
|
||||
input/
|
|
@ -0,0 +1,13 @@
|
|||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
A copy of the GNU General Public License can be found
|
||||
here <http://www.gnu.org/licenses/>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
TPDF - Tellico Parser anD Finder
|
||||
|
||||
A simple Tellico XML parser and finder for your book library, written in Python3
|
|
@ -0,0 +1 @@
|
|||
- Properly automagically read interesting parts of XML into JSON
|
|
@ -0,0 +1,24 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="stylesheet" media="all" type="text/css" href="style.css" />
|
||||
<title>TPDF - Tellico Parser anD Finder</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>TPDF - Tellico Parser anD Finder</h1>
|
||||
|
||||
<form action="main.py" method="get">
|
||||
<label for="title">Title</label>
|
||||
<input type="text" name="title" />
|
||||
|
||||
<label for="author">Author</label>
|
||||
<input type="text" name="author" />
|
||||
|
||||
<input type="submit" />
|
||||
<input type="reset" />
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,70 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: UTF-8 -*-
|
||||
|
||||
# GET me using a web browser,
|
||||
# executing my code with a Python interpreter called by a CGI-compliant webserver!
|
||||
# Example URI:
|
||||
# http://www.example.org/path/main.py?format=format&title=title&author=author
|
||||
# where:
|
||||
# format:
|
||||
# choose output format. Can be either `json` or `html` (default)
|
||||
# title:
|
||||
# title of the book to filter (optional)
|
||||
# author:
|
||||
# author of the book to filter (optional)
|
||||
#
|
||||
# Every parameter is optional.
|
||||
# Please note that not providing filters results in all books in the library.
|
||||
|
||||
# Useful libraries (no pun intended)
|
||||
import xml.etree.ElementTree as ET
|
||||
import json
|
||||
import sys
|
||||
import cgitb, cgi
|
||||
|
||||
# Our custom library (again no pun intended)
|
||||
import tcparser
|
||||
|
||||
# Start CGI handling for webserver
|
||||
cgitb.enable()
|
||||
inputvars = cgi.FieldStorage()
|
||||
|
||||
# Detect desired format
|
||||
try:
|
||||
format = inputvars['format'].value
|
||||
except KeyError:
|
||||
format = 'html'
|
||||
|
||||
if format == 'html':
|
||||
print('Content-Type: text/html; charset=utf-8')
|
||||
else:
|
||||
print('Content-Type: text/json; charset=utf-8')
|
||||
|
||||
print()
|
||||
|
||||
### End of HTTP headers: it is now safe to output things
|
||||
##########################################################
|
||||
|
||||
# Get a Python-friendly library struct
|
||||
library = tcparser.getLibrary('input/tellico.xml')
|
||||
|
||||
### Get filters to search for books ###
|
||||
try:
|
||||
title = inputvars['title'].value
|
||||
except KeyError:
|
||||
title = ''
|
||||
|
||||
try:
|
||||
author = inputvars['author'].value
|
||||
except KeyError:
|
||||
author = ''
|
||||
|
||||
|
||||
result = tcparser.filter(library, title=title, author=author)
|
||||
|
||||
if format == 'html':
|
||||
html = tcparser.getHTML(result)
|
||||
ET.dump(html)
|
||||
if format == 'json':
|
||||
# Wanna get a pretty JSON encoded library to do your nasty things offline at home? ;-)
|
||||
print(json.dumps(result, indent=4))
|
|
@ -0,0 +1,14 @@
|
|||
@charset "utf-8";
|
||||
|
||||
body {
|
||||
background-color: #FFCECE;
|
||||
}
|
||||
|
||||
table {
|
||||
border: 1px solid black;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
td {
|
||||
border: 1px solid black;
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
import xml.etree.ElementTree as ET
|
||||
import json
|
||||
|
||||
# Parse Tellico's XML and get a library struct,
|
||||
# a stripped version of our library in a Python-friendly format
|
||||
def getLibrary(path):
|
||||
# Get XML string from file
|
||||
fh = open(path)
|
||||
xmlstring = fh.read()
|
||||
# Get rid of XML namespace
|
||||
xmlstring = xmlstring.replace('xmlns="http://periapsis.org/tellico/"', '')
|
||||
|
||||
root = ET.fromstring(xmlstring)
|
||||
|
||||
if root[0].tag != 'collection':
|
||||
sys.exit('No collection found')
|
||||
|
||||
collection = root[0]
|
||||
|
||||
library = list()
|
||||
|
||||
for i in collection.findall('entry'):
|
||||
newbook = dict()
|
||||
newbook['id'] = int(i.attrib['id'])
|
||||
# these `for` overwrite previous values,
|
||||
# but it is not an issue since actually these are one shot only elements
|
||||
for j in i.iter('title'):
|
||||
newbook['title'] = j.text
|
||||
for j in i.iter('publisher'):
|
||||
newbook['publisher'] = j.text
|
||||
for j in i.iter('pub_year'):
|
||||
newbook['year'] = int(j.text)
|
||||
for j in i.iter('isbn'):
|
||||
newbook['isbn'] = j.text.replace('-', '')
|
||||
for j in i.iter('pages'):
|
||||
newbook['pages'] = int(j.text)
|
||||
newbook['authors'] = list()
|
||||
for j in i.iter('authors'):
|
||||
for k in j.findall('author'):
|
||||
newbook['authors'].append(k.text)
|
||||
|
||||
library.append(newbook)
|
||||
|
||||
return library
|
||||
|
||||
# Given a custom Python-friendly library struct, get the HTML version of it
|
||||
# Very useful for our webserver
|
||||
def getHTML(library):
|
||||
# Build the XML/HTML tree
|
||||
tree = ET.ElementTree()
|
||||
|
||||
# Headers and other stuff needed for properly formatted HTML documents
|
||||
html = ET.Element('html')
|
||||
head = ET.Element('head')
|
||||
title = ET.Element('title')
|
||||
linkstyle = ET.Element('link', attrib={'rel': 'stylesheet', 'type': 'text/css', 'media':'all', 'href': 'style.css'})
|
||||
metacharset = ET.Element('meta', attrib={'charset': 'utf-8'})
|
||||
body = ET.Element('body')
|
||||
main = ET.Element('main')
|
||||
table = ET.Element('table')
|
||||
|
||||
title.text = 'Tellico parsed Library HTML'
|
||||
|
||||
tree._setroot(html)
|
||||
html.append(head)
|
||||
head.append(title)
|
||||
head.append(metacharset)
|
||||
head.append(linkstyle)
|
||||
html.append(body)
|
||||
body.append(main)
|
||||
main.append(table)
|
||||
|
||||
# Add a row in our table for every book in the library object
|
||||
for i in library:
|
||||
tr = ET.Element('tr')
|
||||
|
||||
id = ET.Element('td')
|
||||
id.text = str(i.get('id'))
|
||||
tr.append(id)
|
||||
|
||||
title = ET.Element('td')
|
||||
title.text = i.get('title')
|
||||
tr.append(title)
|
||||
|
||||
publisher = ET.Element('td');
|
||||
publisher.text = i.get('publisher')
|
||||
tr.append(publisher)
|
||||
|
||||
year = ET.Element('td')
|
||||
year.text = str(i.get('year'))
|
||||
tr.append(year)
|
||||
|
||||
isbn = ET.Element('td')
|
||||
isbn.text = i.get('isbn')
|
||||
tr.append(isbn)
|
||||
|
||||
pages = ET.Element('td')
|
||||
pages.text = str(i.get('pages'))
|
||||
tr.append(pages)
|
||||
|
||||
authors = ET.Element('td')
|
||||
ul = ET.Element('ul')
|
||||
authors.append(ul)
|
||||
for j in i['authors']:
|
||||
li = ET.Element('li')
|
||||
li.text = j
|
||||
ul.append(li)
|
||||
tr.append(authors)
|
||||
|
||||
table.append(tr)
|
||||
|
||||
# Our nice XML/HTML tree
|
||||
return tree
|
||||
|
||||
# Filter results using following filter functions
|
||||
##################################################
|
||||
def filter(library, title='', author=''):
|
||||
# print ("<pre>" + json.dumps(library, indent=4) + "</pre>")
|
||||
result = list()
|
||||
|
||||
for i in library:
|
||||
if filterTitle(i, title) and filterAuthor(i, author):
|
||||
result.append(i)
|
||||
|
||||
return result
|
||||
|
||||
# Filter by title
|
||||
def filterTitle(book, filter):
|
||||
return filter.lower() in book['title'].lower()
|
||||
|
||||
# Filter by author
|
||||
def filterAuthor(book, filter):
|
||||
for i in book['authors']:
|
||||
if filter.lower() in i.lower():
|
||||
return True
|
||||
return False
|
Loading…
Reference in New Issue