Bible Parser Flutter
A Flutter package for parsing Bible texts in OSIS, USFX, and ZEFANIA XML formats with both direct parsing and database-backed approaches. Now includes a desktop app for Bible database creation and management!
๐ v0.4.0 Features
- โ
Footnote Support: Parse and display USFX
<f>footnotes with inline markers and full content - โ
Updated DB Schema: New
verse_footnotestable (database version 5) - โ
Footnoteclass: New public API type withid,marker,content - โ
Verse.hasFootnotes: Convenience getter onVerse - โ
TextSegment.isFootnoteMarker: Identify footnote positions within segments
v0.3.0 Features
- โ Desktop App: Complete Bible database creation tool
- โ Database Export: User-controlled file saving
- โ Database Loading: Direct database file loading
- โ Cross-Platform: macOS, Windows, Linux support
- โ Production Workflow: XML โ Database โ Mobile App Distribution
๐ฑ Desktop App Usage
Installation & Setup
# Clone the repository to get the desktop app
git clone https://github.com/Omarzintan/bible_parser_flutter.git
cd bible_parser_flutter
# Navigate to desktop app
cd desktop_app
flutter pub get
flutter run -d macos # or -d windows, -d linux
Alternative: Download Desktop App Only
If you only want the desktop app without the full package:
# Clone and checkout only the desktop app
git clone --filter=blob:'desktop_app/*' https://github.com/Omarzintan/bible_parser_flutter.git
cd bible_parser_flutter/desktop_app
flutter pub get
flutter run -d macos
Workflow
- Create Database: Select XML file โ Click "Create Database"
- Download: Click "Download" โ Choose save location (Desktop, Documents, etc.)
- Test: Switch to "Load from Database" mode โ Test exported file
- Deploy: Upload db file to any storage service (Firebase, Google Drive, etc.)
File Management
- Temporary Storage: Databases created in app's
dbfiles/directory - Persistence: Files remain after stopping
flutter run - Overwrite: Creating same database name overwrites previous file
- Download: User saves to permanent location of their choice
๐ฆ Package Contents
Core Library (lib/)
- Bible parsing for OSIS, USFX, and ZEFANIA XML formats
- Database repository with SQLite caching
- Text segments for red-letter and added text support
- Cross-platform mobile and web support
Desktop App (desktop_app/)
- GUI tool for Bible database creation and management
- Cross-platform desktop support (macOS, Windows, Linux)
- File picker integration for XML selection
- Database export with user-controlled saving
- Database loading for testing exported files
- Production workflow ready for Firebase distribution
Note: The desktop app is included in the Git repository but excluded from the published Flutter package to keep the package size reasonable. Clone the repository to access the desktop app.
- ๐ Red-Letter Bible Support - Identify and style Jesus' words in OSIS and USFX formats
- ๐ Added Text Support - Track translator additions (italicized text) in OSIS and USFX formats
- ๐ Footnote Support - Parse and access USFX footnotes with position markers in verse segments
- Parse Bible texts in multiple formats (USFX, OSIS, ZEFANIA)
- Automatic format detection
- Memory-efficient SAX-style XML parsing using proper async streams
- Note: This package has only been tested to work with the XML files under example/assets/open-bibles. Users are welcome to try the parser with other XML files and create a GitHub issue if they encounter any errors.
- Database caching with automatic segment persistence
- Search functionality for verses
- Retrieve verses by book and chapter
- Cross-platform support (iOS, Android, Web, Windows, Linux, macOS)
Getting Started
Installation
Add this to your package's pubspec.yaml file:
dependencies:
bible_parser_flutter: ^0.4.0
Then run:
flutter pub get
Prerequisites
- Flutter SDK
- A Bible XML file in one of the supported formats (USFX, OSIS, ZEFANIA)
Usage
Direct Parsing Approach
Parse a Bible file directly without database caching. This is simpler but less efficient for repeated access:
import 'dart:io';
import 'package:bible_parser_flutter/bible_parser_flutter.dart';
Future<void> parseBible() async {
// Load the XML content from assets
final xmlString =
await DefaultAssetBundle.of(context).loadString(xmlPath);
// Create the original parser with the XML string
final parser = BibleParser.fromString(xmlString,
format: currentFormat.name.toUpperCase());
// Access books
await for (final book in parser.books) {
print('${book.title} (${book.id})');
// Access chapters and verses
for (final chapter in book.chapters) {
for (final verse in chapter.verses) {
print('${book.id} ${verse.chapterNum}:${verse.num} - ${verse.text}');
}
}
}
// Or access all verses directly
await for (final verse in parser.verses) {
print('${verse.bookId} ${verse.chapterNum}:${verse.num} - ${verse.text}');
}
}
๐ Database Loading (Recommended for Production)
Load from pre-created database files for instant startup and optimal performance:
import 'package:bible_parser_flutter/bible_parser_flutter.dart';
// Load from pre-created database file (instant startup)
final repository = BibleRepository.fromDatabase();
await repository.initialize('path/to/eng-kjv.osis.db');
// Get books, chapters, verses instantly (no XML parsing)
final books = await repository.getBooks();
final verses = await repository.getVerses('John', 1, 1);
// Support for red-letter and added text
for (final verse in verses) {
for (final segment in verse.segments ?? []) {
if (segment.isJesus) {
// Render in red (Jesus' words)
print('Jesus: "${segment.text}"');
} else if (segment.isAdded) {
// Render in italics (translator additions)
print('Added: "${segment.text}"');
} else {
// Normal text
print('Text: "${segment.text}"');
}
}
}
// Search functionality
final searchResults = await repository.searchVerses('love');
print('Found ${searchResults.length} verses containing "love"');
// Don't forget to close when done
await repository.close();
Production Workflow:
- Use the desktop app to create database files from XML
- Upload database files to Firebase Storage or cloud service
- Download and load in mobile app using
BibleRepository.fromDatabase()
Benefits:
- โก Instant startup - No XML parsing needed
- ๐ฑ Mobile optimized - Smaller app size, faster performance
- ๐ Easy updates - Update databases without app updates
- ๐จ Full features - Red-letter, added text, search support
Database Repository Approach
Parse XML and cache in a database for repeated access. This is more efficient for apps that need frequent Bible access:
import 'package:bible_parser_flutter/bible_parser_flutter.dart';
// Parse XML and create database
final repository = BibleRepository.fromString(
xmlString: xmlContent,
format: 'OSIS', // or 'USFX', 'ZEFANIA'
);
await repository.initialize('my_bible.db');
// Get books
final books = await repository.getBooks();
// Get verses from a specific chapter
final verses = await repository.getVerses('gen', 1);
for (final verse in verses) {
print('${verse.bookId} ${verse.chapterNum}:${verse.num} - ${verse.text}');
}
// Search for verses containing specific text
final searchResults = await repository.searchVerses('love');
print('Found ${searchResults.length} verses containing "love"');
// Don't forget to close when done
await repository.close();
Use this approach when:
- ๐ฑ Building a Bible app with frequent access
- ๐ Need to switch between books/chapters quickly
- ๐ Want search functionality
- ๐พ Have storage space for database caching
Red-Letter Bible Support (New in v0.2.0)
Access Jesus' words with text segments:
// Parse a Bible with red-letter support
final parser = BibleParser.fromString(xmlString, format: 'OSIS');
await for (final verse in parser.verses) {
// Check if verse contains Jesus' words
if (verse.hasJesusWords) {
print('Verse ${verse.chapterNum}:${verse.num} has Jesus speaking!');
// Access individual segments
for (final segment in verse.segments!) {
if (segment.isJesus) {
// Display in red or special styling
print('Jesus said: "${segment.text}"');
} else {
// Display normally
print('Narrator: "${segment.text}"');
}
}
}
// Or just use the full text (backward compatible)
print(verse.text);
}
Supported formats:
- OSIS:
<q who="Jesus">tags - USFX:
<wj>(Words of Jesus) tags
Database persistence: Segments are automatically saved and loaded from the database when using BibleRepository.
For more details, see the Red-Letter Bible Support documentation.
Added/Italicized Text Support
The parser also tracks text marked as translator additions (typically italicized in printed Bibles):
// Get a verse with added text
final verse = await repository.getVerse('Matt', 27, 65);
if (verse.segments != null) {
for (final segment in verse.segments!) {
if (segment.isAdded) {
// Display in italics (translator addition)
print('Italic: "${segment.text}"');
} else if (segment.isJesus) {
// Display in red (Jesus' words)
print('Red: "${segment.text}"');
} else {
// Display normally
print('Normal: "${segment.text}"');
}
}
}
Supported formats:
- OSIS:
<transChange type="added">tags - USFX:
<add>tags
Example: In Matthew 27:65 KJV, the word "it" is marked as added text:
Pilate said unto them, Ye have a watch: go your way, make it as sure as ye can.
Footnote Support (USFX)
Access footnotes attached to verses. Footnote positions are encoded as marker segments within verse.segments, and the full footnote content is available via verse.footnotes:
final verse = await repository.getVerse('gen', 1, 1);
// Check if verse has footnotes
if (verse.hasFootnotes) {
// Render segments - some mark footnote positions
for (final segment in verse.segments ?? []) {
if (segment.isFootnoteMarker) {
// Find the matching footnote and insert its marker
final fn = verse.footnotes!
.firstWhere((f) => f.id == segment.footnoteId);
print(fn.marker); // e.g. "ยน"
} else {
print(segment.text); // normal, Jesus, or added text
}
}
// Display footnote list at bottom of verse
for (final fn in verse.footnotes!) {
print('${fn.marker} ${fn.content}');
// e.g. "ยน Hebrew: bara (to create)"
}
}
Supported formats:
- USFX:
<f>tags
Note: Footnotes are parsed and persisted to the database automatically when using BibleRepository. The verse.text field is never polluted with footnote content.
Performance Considerations
Direct Parsing
- Simple implementation
- No database setup required
- Always uses the latest source files
- CPU and memory intensive
- Slower initial load times
- Higher battery consumption
- Repeated parsing on each access
Database Approach
- Much faster access once data is loaded
- Lower memory usage during normal operation
- Better user experience with instant search and navigation
- Reduced battery consumption
- Works offline without re-parsing
- Requires initial setup complexity
Example
See the /example folder for a complete working example of both approaches. The example app demonstrates:
- Parsing Bible files in OSIS and USFX formats
- Database initialization and querying
- Browsing verses by book and chapter selection
License
This project is licensed under the MIT License - see the LICENSE file for details.
Acknowledgments
Inspired by the Ruby bible_parser library.
Bible XML files in the example are from:
- open-bibles GitHub repository
- eBible.org - Free Bible translations in many languages