PHPackages                             renanbr/bibtex-parser - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Parsing &amp; Serialization](/categories/parsing)
4. /
5. renanbr/bibtex-parser

ActiveLibrary[Parsing &amp; Serialization](/categories/parsing)

renanbr/bibtex-parser
=====================

BibTex Parser provides an API to read .bib files programmatically

2.2.0(2y ago)39381.9k—9%16[1 PRs](https://github.com/renanbr/bibtex-parser/pulls)8MITPHPPHP &gt;=5.6.0CI passing

Since Nov 29Pushed 10mo ago4 watchersCompare

[ Source](https://github.com/renanbr/bibtex-parser)[ Packagist](https://packagist.org/packages/renanbr/bibtex-parser)[ RSS](/packages/renanbr-bibtex-parser/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (2)Versions (21)Used By (8)

PHP BibTeX Parser 2.x
=====================

[](#php-bibtex-parser-2x)

 This is a [BibTeX](https://tug.org/bibtex/) parser written in [PHP](https://php.net).

 [ ![BibTeX logo](https://camo.githubusercontent.com/345b12da4791809f6391e5343dd394b74c7f65a4c76d9cac816563b6859a6441/68747470733a2f2f75706c6f61642e77696b696d656469612e6f72672f77696b6970656469612f636f6d6d6f6e732f332f33302f4269625465585f6c6f676f2e737667) ](https://tug.org/bibtex/) [ ![PHP logo](https://camo.githubusercontent.com/4483bf574aa290f3a83765b3f21279c4478760d0074d01e3a2a79ac14ff4ac7e/68747470733a2f2f75706c6f61642e77696b696d656469612e6f72672f77696b6970656469612f636f6d6d6f6e732f322f32372f5048502d6c6f676f2e737667) ](https://php.net)

[![Tests](https://github.com/renanbr/bibtex-parser/workflows/Tests/badge.svg)](https://github.com/renanbr/bibtex-parser/workflows/Tests/badge.svg)[![Static Analysis](https://github.com/renanbr/bibtex-parser/workflows/Static%20Analysis/badge.svg)](https://github.com/renanbr/bibtex-parser/workflows/Static%20Analysis/badge.svg)[![Coding Standards](https://github.com/renanbr/bibtex-parser/workflows/Coding%20Standards/badge.svg)](https://github.com/renanbr/bibtex-parser/workflows/Coding%20Standards/badge.svg)

You are browsing the documentation of **BibTeX Parser 2.x**, the latest version.

Table of contents
-----------------

[](#table-of-contents)

- [Installing](#installing)
- [Usage](#usage)
- [Vocabulary](#vocabulary)
- [Processors](#processors)
    - [Tag name case](#tag-name-case)
    - [Authors and editors](#authors-and-editors)
    - [Keywords](#keywords)
    - [Date](#date)
    - [Fill missing tag](#fill-missing-tag)
    - [Trim tags](#trim-tags)
    - [Determine URL from the DOI](#determine-url-from-the-doi)
    - [LaTeX to unicode](#latex-to-unicode)
    - [Custom](#custom)
- [Handling errors](#handling-errors)
- [Advanced usage](#advanced-usage)
- [Release Policy](#release-policy)
    - [Dependencies Compatibility Policy](#dependencies-compatibility-policy)

Installing
----------

[](#installing)

```
composer require renanbr/bibtex-parser
```

Usage
-----

[](#usage)

```
use RenanBr\BibTexParser\Listener;
use RenanBr\BibTexParser\Parser;
use RenanBr\BibTexParser\Processor;

require 'vendor/autoload.php';

$bibtex = addProcessor(new Processor\KeywordsProcessor());
// $listener->addProcessor(new Processor\DateProcessor());
// $listener->addProcessor(new Processor\FillMissingProcessor([/* ... */]));
// $listener->addProcessor(new Processor\TrimProcessor());
// $listener->addProcessor(new Processor\UrlFromDoiProcessor());
// $listener->addProcessor(new Processor\LatexToUnicodeProcessor());
// ... you can append as many Processors as you want

// Create a Parser and attach the listener
$parser = new Parser();
$parser->addListener($listener);

// Parse the content, then read processed data from the Listener
$parser->parseString($bibtex); // or parseFile('/path/to/file.bib')
$entries = $listener->export();

print_r($entries);
```

This will output:

```
Array
(
    [0] => Array
        (
            [_type] => article
            [citation-key] => einstein1916relativity
            [title] => Relativity: The Special and General Theory
            [author] => Einstein, Albert
            [year] => 1916
        )
)

```

Vocabulary
----------

[](#vocabulary)

[BibTeX](https://tug.org/bibtex/) is all about "entry", "tag's name" and "tag's content".

> A [BibTeX](https://tug.org/bibtex/) **entry** consists of the type (the word after @), a citation-key and a number of tags which define various characteristics of the specific [BibTeX](https://tug.org/bibtex/) entry. (...) A [BibTeX](https://tug.org/bibtex/) **tag** is specified by its **name** followed by an equals sign, and the **content**.

Source:

Note: This library considers "type" and "citation-key" as tags. This behavior can be changed [implementing your own Listener](#advanced-usage).

Processors
----------

[](#processors)

`Processor` is a [callable](https://php.net/manual/en/language.types.callable.php) that receives an entry as argument and returns a modified entry.

This library contains three main parts:

- `Parser` class, responsible for detecting units inside a [BibTeX](https://tug.org/bibtex/) input;
- `Listener` class, responsible for gathering units and transforming them into a list of entries;
- `Processor` classes, responsible for manipulating entries.

Despite you can't configure the `Parser`, you can append as many `Processor` as you want to the `Listener` through `Listener::addProcessor()` before exporting the contents. Be aware that `Listener` provides, by default, these features:

- Found entries are reachable through `Listener::export()` method;
- [Tag content concatenation](http://www.bibtex.org/Format/);
    - e.g. `hello # " world"` tag's content will generate `hello world` [string](https://php.net/manual/language.types.string.php)
- [Tag content abbreviation handling](http://www.bibtex.org/Format/);
    - e.g. `@string{foo="bar"} @misc{bar=foo}` will make `$entries[1]['bar']` assume `bar` as value
- Publication's type exposed as `_type` tag;
- Citation key exposed as `citation-key` tag;
- Original entry text exposed as `_original` tag.

This project ships some useful processors.

### Tag name case

[](#tag-name-case)

In [BibTeX](https://tug.org/bibtex/) the tag's names aren't case-sensitive. This library exposes entries as [array](https://php.net/manual/language.types.array.php), in which keys are case-sensitive. To avoid this misunderstanding, you can force the tags' name character case using `TagNameCaseProcessor`.

Usage```
use RenanBr\BibTexParser\Processor\TagNameCaseProcessor;

$listener->addProcessor(new TagNameCaseProcessor(CASE_UPPER)); // or CASE_LOWER
```

```
@article{
  title={BibTeX rocks}
}
```

```
Array
(
    [0] => Array
        (
            [TYPE] => article
            [TITLE] => BibTeX rocks
        )
)

```

### Authors and editors

[](#authors-and-editors)

[BibTeX](https://tug.org/bibtex/) recognizes four parts of an author's name: First Von Last Jr. If you would like to parse the `author` and `editor` tags included in your entries, you can use the `NamesProcessor` class.

Usage```
use RenanBr\BibTexParser\Processor\NamesProcessor;

$listener->addProcessor(new NamesProcessor());
```

```
@article{
  title={Relativity: The Special and General Theory},
  author={Einstein, Albert}
}
```

```
Array
(
    [0] => Array
        (
            [type] => article
            [title] => Relativity: The Special and General Theory
            [author] => Array
                (
                    [0] => Array
                        (
                            [first] => Albert
                            [von] =>
                            [last] => Einstein
                            [jr] =>
                        )
                )
        )
)

```

### Keywords

[](#keywords)

The `keywords` tag contains a list of expressions represented as [string](https://php.net/manual/language.types.string.php), you might want to read them as an [array](https://php.net/manual/language.types.array.php) instead.

Usage```
use RenanBr\BibTexParser\Processor\KeywordsProcessor;

$listener->addProcessor(new KeywordsProcessor());
```

```
@misc{
  title={The End of Theory: The Data Deluge Makes the Scientific Method Obsolete},
  keywords={big data, data deluge, scientific method}
}
```

```
Array
(
    [0] => Array
        (
            [type] => misc
            [title] => The End of Theory: The Data Deluge Makes the Scientific Method Obsolete
            [keywords] => Array
                (
                    [0] => big data
                    [1] => data deluge
                    [2] => scientific method
                )
        )
)

```

### Date

[](#date)

It adds a new tag `_date` as [DateTimeImmutable](https://www.php.net/manual/class.datetimeimmutable.php). This processor adds the new tag **if and only if** this the tags `month` and `year` are fulfilled.

Usage```
use RenanBr\BibTexParser\Processor\DateProcessor;

$listener->addProcessor(new DateProcessor());
```

```
@misc{
  month="1~oct",
  year=2000
}
```

```
Array
(
    [0] => Array
        (
            [type] => misc
            [month] => 1~oct
            [year] => 2000
            [_date] => DateTimeImmutable Object
                (
                    [date] => 2000-10-01 00:00:00.000000
                    [timezone_type] => 3
                    [timezone] => UTC
                )
        )
)

```

### Fill missing tag

[](#fill-missing-tag)

It puts a default value to some missing field.

Usage```
use RenanBr\BibTexParser\Processor\FillMissingProcessor;

$listener->addProcessor(new FillMissingProcessor([
    'title' => 'This entry has no title',
    'year' => 1970,
]));
```

```
@misc{
}

@misc{
    title="I do exist"
}
```

```
Array
(
    [0] => Array
        (
            [type] => misc
            [title] => This entry has no title
            [year] => 1970
        )
    [1] => Array
        (
            [type] => misc
            [title] => I do exist
            [year] => 1970
        )
)

```

### Trim tags

[](#trim-tags)

Apply [trim()](https://www.php.net/trim) to all tags.

Usage```
use RenanBr\BibTexParser\Processor\TrimProcessor;

$listener->addProcessor(new TrimProcessor());
```

```
@misc{
  title=" too much space  "
}
```

```
Array
(
    [0] => Array
        (
            [type] => misc
            [title] => too much space
        )

)

```

### Determine URL from the DOI

[](#determine-url-from-the-doi)

Sets `url` tag with [DOI](https://www.doi.org/) if `doi` tag is present and `url` tag is missing.

Usage```
use RenanBr\BibTexParser\Processor\UrlFromDoiProcessor;

$listener->addProcessor(new UrlFromDoiProcessor());
```

```
@misc{
  doi="qwerty"
}

@misc{
  doi="azerty",
  url="http://example.org"
}
```

```
Array
(
    [0] => Array
        (
            [type] => misc
            [doi] => qwerty
            [url] => https://doi.org/qwerty
        )

    [1] => Array
        (
            [type] => misc
            [doi] => azerty
            [url] => http://example.org
        )
)

```

### LaTeX to unicode

[](#latex-to-unicode)

[BibTeX](https://tug.org/bibtex/) files store [LaTeX](https://www.latex-project.org/) contents. You might want to read them as unicode instead. The `LatexToUnicodeProcessor` class solves this problem, but before adding the processor to the listener you must:

- [install Pandoc](http://pandoc.org/installing.html) in your system; and
- add [ryakad/pandoc-php](https://github.com/ryakad/pandoc-php) or [ueberdosis/pandoc](https://github.com/ueberdosis/pandoc) as a dependency of your project.

Usage```
use RenanBr\BibTexParser\Processor\LatexToUnicodeProcessor;

$listener->addProcessor(new LatexToUnicodeProcessor());
```

```
@article{
  title={Caf\\'{e}s and bars}
}
```

```
Array
(
    [0] => Array
        (
            [type] => article
            [title] => Cafés and bars
        )
)

```

Note: Order matters, add this processor as the last.

### Custom

[](#custom)

The `Listener::addProcessor()` method expects a [callable](https://php.net/manual/en/language.types.callable.php) as argument. In the example shown below, we append the text `with laser` to the `title` tags for all entries.

Usage```
$listener->addProcessor(static function (array $entry) {
    $entry['title'] .= ' with laser';
    return $entry;
});
```

```
@article{
  title={BibTeX rocks}
}

```

```
Array
(
    [0] => Array
        (
            [type] => article
            [title] => BibTeX rocks with laser
        )
)

```

Handling errors
---------------

[](#handling-errors)

This library throws two types of exception: `ParserException` and `ProcessorException`. The first one may happen during the data extraction. When it occurs it probably means the parsed BibTeX isn't valid. The second exception may happen during the data processing. When it occurs it means the listener's processors can't handle properly the data found. Both implement `ExceptionInterface`.

```
use RenanBr\BibTexParser\Exception\ExceptionInterface;
use RenanBr\BibTexParser\Exception\ParserException;
use RenanBr\BibTexParser\Exception\ProcessorException;

try {
    // ... parser and listener configuration

    $parser->parseFile('/path/to/file.bib');
    $entries = $listener->export();
} catch (ParserException $exception) {
    // The BibTeX isn't valid
} catch (ProcessorException $exception) {
    // Listener's processors aren't able to handle data found
} catch (ExceptionInterface $exception) {
    // Alternatively, you can use this exception to catch all of them at once
}
```

Advanced usage
--------------

[](#advanced-usage)

The core of this library contains these main classes:

- `RenanBr\BibTexParser\Parser` responsible for detecting units inside a [BibTeX](https://tug.org/bibtex/) input;
- `RenanBr\BibTexParser\ListenerInterface` responsible for treating units found.

You can attach listeners to the parser through `Parser::addListener()`. The parser is able to detect [BibTeX](https://tug.org/bibtex/) units, such as "type", "tag's name", "tag's content". As the parser finds a unit, it triggers the listeners attached to it.

You can code your own listener! All you have to do is handle units.

```
namespace RenanBr\BibTexParser;

interface ListenerInterface
{
    /**
     * Called when an unit is found.
     *
     * @param string $text    The original content of the unit found.
     *                        Escape character will not be sent.
     * @param string $type    The type of unit found.
     *                        It can assume one of Parser's constant value.
     * @param array  $context Contains details of the unit found.
     */
    public function bibTexUnitFound($text, $type, array $context);
}
```

`$type` may assume one of these values:

- `Parser::TYPE`
- `Parser::CITATION_KEY`
- `Parser::TAG_NAME`
- `Parser::RAW_TAG_CONTENT`
- `Parser::BRACED_TAG_CONTENT`
- `Parser::QUOTED_TAG_CONTENT`
- `Parser::ENTRY`

`$context` is an [array](https://php.net/manual/language.types.array.php) with these keys:

- `offset` contains the `$text`'s beginning position. It may be useful, for example, to [seek on a file pointer](https://php.net/fseek);
- `length` contains the original `$text`'s length. It may differ from [string](https://php.net/manual/language.types.string.php) length sent to the listener because may there are escaped characters.

Release Policy
--------------

[](#release-policy)

There is a **single** maintained branch per time. This branch targets a minor version.

A maintained version reaches its end-of-life when a new minor version is released.

### Dependencies Compatibility Policy

[](#dependencies-compatibility-policy)

This library is compatible with maintained versions of [PHP](https://www.php.net/supported-versions.php).

###  Health Score

49

—

FairBetter than 95% of packages

Maintenance39

Infrequent updates — may be unmaintained

Popularity49

Moderate usage in the ecosystem

Community31

Small or concentrated contributor base

Maturity67

Established project with proven stability

 Bus Factor1

Top contributor holds 88.1% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~129 days

Recently: every ~295 days

Total

20

Last Release

998d ago

Major Versions

0.6.0 → 1.0.02017-10-11

1.0.3 → 2.0.02017-11-25

1.0.4 → 2.0.12018-02-04

1.x-dev → 2.1.02020-06-03

### Community

Maintainers

![](https://www.gravatar.com/avatar/4e1aa2e77d3574f9aa318fde02fe0f6113404f44c244529caceed0e1dadf4b66?d=identicon)[renanbr](/maintainers/renanbr)

---

Top Contributors

[![renanbr](https://avatars.githubusercontent.com/u/350222?v=4)](https://github.com/renanbr "renanbr (193 commits)")[![andrechalom](https://avatars.githubusercontent.com/u/1994997?v=4)](https://github.com/andrechalom "andrechalom (10 commits)")[![MarionLeHerisson](https://avatars.githubusercontent.com/u/11477247?v=4)](https://github.com/MarionLeHerisson "MarionLeHerisson (4 commits)")[![LeJeanbono](https://avatars.githubusercontent.com/u/11347342?v=4)](https://github.com/LeJeanbono "LeJeanbono (3 commits)")[![raphael-st](https://avatars.githubusercontent.com/u/21144687?v=4)](https://github.com/raphael-st "raphael-st (2 commits)")[![saschaszott](https://avatars.githubusercontent.com/u/952735?v=4)](https://github.com/saschaszott "saschaszott (2 commits)")[![eknoes](https://avatars.githubusercontent.com/u/3641205?v=4)](https://github.com/eknoes "eknoes (1 commits)")[![icanhazstring](https://avatars.githubusercontent.com/u/883543?v=4)](https://github.com/icanhazstring "icanhazstring (1 commits)")[![arandilopez](https://avatars.githubusercontent.com/u/2985233?v=4)](https://github.com/arandilopez "arandilopez (1 commits)")[![tspencer244](https://avatars.githubusercontent.com/u/15922667?v=4)](https://github.com/tspencer244 "tspencer244 (1 commits)")[![extracts](https://avatars.githubusercontent.com/u/1410036?v=4)](https://github.com/extracts "extracts (1 commits)")

---

Tags

bibbibtexparserphpparserBibliographylatexcitationbibtexcitebib

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/renanbr-bibtex-parser/health.svg)

```
[![Health](https://phpackages.com/badges/renanbr-bibtex-parser/health.svg)](https://phpackages.com/packages/renanbr-bibtex-parser)
```

###  Alternatives

[nikic/php-parser

A PHP parser written in PHP

17.4k902.6M1.8k](/packages/nikic-php-parser)[doctrine/lexer

PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.

11.2k910.8M118](/packages/doctrine-lexer)[erusev/parsedown

Parser for Markdown.

15.0k151.8M732](/packages/erusev-parsedown)[league/commonmark

Highly-extensible PHP Markdown parser which fully supports the CommonMark spec and GitHub-Flavored Markdown (GFM)

3.0k404.0M702](/packages/league-commonmark)[masterminds/html5

An HTML5 parser and serializer.

1.8k242.8M229](/packages/masterminds-html5)[sabberworm/php-css-parser

Parser for CSS Files written in PHP

1.8k191.2M65](/packages/sabberworm-php-css-parser)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
