{"id":17875871,"url":"https://github.com/pietercolpaert/hardf","last_synced_at":"2025-09-02T10:31:53.621Z","repository":{"id":53451301,"uuid":"86425710","full_name":"pietercolpaert/hardf","owner":"pietercolpaert","description":"Low level PHP library for RDF1.1 based on N3.js","archived":false,"fork":false,"pushed_at":"2024-06-26T07:50:57.000Z","size":243,"stargazers_count":36,"open_issues_count":2,"forks_count":7,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-12-22T18:07:48.391Z","etag":null,"topics":["linked-data","n-triples","nquads","ntriples","php-library","rdf","trig","triples","turtle"],"latest_commit_sha":null,"homepage":"https://packagist.org/packages/pietercolpaert/hardf","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pietercolpaert.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-03-28T06:56:24.000Z","updated_at":"2024-08-29T07:15:13.000Z","dependencies_parsed_at":"2024-06-18T22:41:24.624Z","dependency_job_id":"6d7560aa-32c1-4e0c-bbbf-37cb1588e083","html_url":"https://github.com/pietercolpaert/hardf","commit_stats":{"total_commits":113,"total_committers":7,"mean_commits":"16.142857142857142","dds":"0.18584070796460173","last_synced_commit":"8dbfb3104ab70e7d43f36016b8ed35e3666ff18c"},"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pietercolpaert%2Fhardf","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pietercolpaert%2Fhardf/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pietercolpaert%2Fhardf/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pietercolpaert%2Fhardf/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pietercolpaert","download_url":"https://codeload.github.com/pietercolpaert/hardf/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":231776536,"owners_count":18424958,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["linked-data","n-triples","nquads","ntriples","php-library","rdf","trig","triples","turtle"],"created_at":"2024-10-28T11:25:46.269Z","updated_at":"2024-12-29T19:23:26.055Z","avatar_url":"https://github.com/pietercolpaert.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# The hardf turtle, n-triples, n-quads, TriG and N3 parser for PHP\n\n**hardf** is a PHP 7.1+ library that lets you handle Linked Data (RDF). It offers:\n - [**Parsing**](#parsing) triples/quads from [Turtle](http://www.w3.org/TR/turtle/), [TriG](http://www.w3.org/TR/trig/), [N-Triples](http://www.w3.org/TR/n-triples/), [N-Quads](http://www.w3.org/TR/n-quads/), and [Notation3 (N3)](https://www.w3.org/TeamSubmission/n3/)\n - [**Writing**](#writing) triples/quads to [Turtle](http://www.w3.org/TR/turtle/), [TriG](http://www.w3.org/TR/trig/), [N-Triples](http://www.w3.org/TR/n-triples/), and [N-Quads](http://www.w3.org/TR/n-quads/)\n\nBoth the parser as the serializer have _streaming_ support.\n\n_This library is a port of [N3.js](https://github.com/rdfjs/N3.js/tree/v0.10.0) to PHP_\n\n## Triple Representation\n\nWe use the triple representation in  PHP ported from NodeJS N3.js library. Check https://github.com/rdfjs/N3.js/tree/v0.10.0#triple-representation for more information\n\nOn purpose, we focused on performance, and not on developer friendliness.\nWe have thus implemented this triple representation using associative arrays rather than PHP object. Thus, the same that holds for N3.js, is now an array. E.g.:\n\n```php\n\u003c?php\n$triple = [\n    'subject' =\u003e   'http://example.org/cartoons#Tom',\n    'predicate' =\u003e 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type',\n    'object' =\u003e    'http://example.org/cartoons#Cat',\n    'graph' =\u003e     'http://example.org/mycartoon', #optional\n    ];\n```\n\nEncode literals as follows (similar to N3.js)\n\n```php\n'\"Tom\"@en-gb' // lowercase language\n'\"1\"^^http://www.w3.org/2001/XMLSchema#integer' // no angular brackets \u003c\u003e\n```\n\n## Library functions\n\nInstall this library using [composer](http://getcomposer.org):\n\n```bash\ncomposer require pietercolpaert/hardf\n```\n\n### Writing\n```php\nuse pietercolpaert\\hardf\\TriGWriter;\n```\n\nA class that should be instantiated and can write TriG or Turtle\n\nExample use:\n```php\n$writer = new TriGWriter([\n    \"prefixes\" =\u003e [\n        \"schema\" =\u003e\"http://schema.org/\",\n        \"dct\" =\u003e\"http://purl.org/dc/terms/\",\n        \"geo\" =\u003e\"http://www.w3.org/2003/01/geo/wgs84_pos#\",\n        \"rdf\" =\u003e \"http://www.w3.org/1999/02/22-rdf-syntax-ns#\",\n        \"rdfs\"=\u003e \"http://www.w3.org/2000/01/rdf-schema#\"\n        ],\n    \"format\" =\u003e \"n-quads\" //Other possible values: n-quads, trig or turtle\n]);\n\n$writer-\u003eaddPrefix(\"ex\",\"http://example.org/\");\n$writer-\u003eaddTriple(\"schema:Person\",\"dct:title\",\"\\\"Person\\\"@en\",\"http://example.org/#test\");\n$writer-\u003eaddTriple(\"schema:Person\",\"schema:label\",\"\\\"Person\\\"@en\",\"http://example.org/#test\");\n$writer-\u003eaddTriple(\"ex:1\",\"dct:title\",\"\\\"Person1\\\"@en\",\"http://example.org/#test\");\n$writer-\u003eaddTriple(\"ex:1\",\"http://www.w3.org/1999/02/22-rdf-syntax-ns#type\",\"schema:Person\",\"http://example.org/#test\");\n$writer-\u003eaddTriple(\"ex:2\",\"dct:title\",\"\\\"Person2\\\"@en\",\"http://example.org/#test\");\n$writer-\u003eaddTriple(\"schema:Person\",\"dct:title\",\"\\\"Person\\\"@en\",\"http://example.org/#test2\");\necho $writer-\u003eend();\n```\n\n#### All methods\n```php\n//The method names should speak for themselves:\n$writer = new TriGWriter([\"prefixes\": [ /* ... */]]);\n$writer-\u003eaddTriple($subject, $predicate, $object, $graphl);\n$writer-\u003eaddTriples($triples);\n$writer-\u003eaddPrefix($prefix, $iri);\n$writer-\u003eaddPrefixes($prefixes);\n//Creates blank node($predicate and/or $object are optional)\n$writer-\u003eblank($predicate, $object);\n//Creates rdf:list with $elements\n$list = $writer-\u003eaddList($elements);\n\n//Returns the current output it is already able to create and clear the internal memory use (useful for streaming)\n$out .= $writer-\u003eread();\n//Alternatively, you can listen for new chunks through a callback:\n$writer-\u003esetReadCallback(function ($output) { echo $output });\n\n//Call this at the end. The return value will be the full triple output, or the rest of the output such as closing dots and brackets, unless a callback was set.\n$out .= $writer-\u003eend();\n//OR\n$writer-\u003eend();\n```\n\n### Parsing\n\nNext to [TriG](https://www.w3.org/TR/trig/), the TriGParser class also parses [Turtle](https://www.w3.org/TR/turtle/), [N-Triples](https://www.w3.org/TR/n-triples/), [N-Quads](https://www.w3.org/TR/n-quads/) and the [W3C Team Submission N3](https://www.w3.org/TeamSubmission/n3/)\n\n#### All methods\n\n```php\n$parser = new TriGParser($options, $tripleCallback, $prefixCallback);\n$parser-\u003esetTripleCallback($function);\n$parser-\u003esetPrefixCallback($function);\n$parser-\u003eparse($input, $tripleCallback, $prefixCallback);\n$parser-\u003eparseChunk($input);\n$parser-\u003eend();\n```\n\n#### Basic examples for small files\n\nUsing return values and passing these to a writer:\n```php\nuse pietercolpaert\\hardf\\TriGParser;\nuse pietercolpaert\\hardf\\TriGWriter;\n$parser = new TriGParser([\"format\" =\u003e \"n-quads\"]); //also parser n-triples, n3, turtle and trig. Format is optional\n$writer = new TriGWriter();\n$triples = $parser-\u003eparse(\"\u003cA\u003e \u003cB\u003e \u003cC\u003e \u003cG\u003e .\");\n$writer-\u003eaddTriples($triples);\necho $writer-\u003eend();\n```\n\nUsing callbacks and passing these to a writer:\n```php\n$parser = new TriGParser();\n$writer = new TriGWriter([\"format\"=\u003e\"trig\"]);\n$parser-\u003eparse(\"\u003chttp://A\u003e \u003chttps://B\u003e \u003chttp://C\u003e \u003chttp://G\u003e . \u003cA2\u003e \u003chttps://B2\u003e \u003chttp://C2\u003e \u003chttp://G3\u003e .\", function ($e, $triple) use ($writer) {\n    if (!isset($e) \u0026\u0026 isset($triple)) {\n        $writer-\u003eaddTriple($triple);\n        echo $writer-\u003eread(); //write out what we have so far\n    } else if (!isset($triple))      // flags the end of the file\n        echo $writer-\u003eend();  //write the end\n    else\n        echo \"Error occured: \" . $e;\n});\n```\n\n#### Example using chunks and keeping prefixes\n\nWhen you need to parse a large file, you will need to parse only chunks and already process them. You can do that as follows:\n\n```php\n$writer = new TriGWriter([\"format\"=\u003e\"n-quads\"]);\n$tripleCallback = function ($error, $triple) use ($writer) {\n    if (isset($error))\n        throw $error;\n    else if (isset($triple)) {\n        $writer-\u003ewrite();\n        echo $writer-\u003eread();\n    else if (isset($error)) {\n        throw $error;\n    } else {\n        echo $writer-\u003eend();\n    }\n};\n$prefixCallback = function ($prefix, $iri) use (\u0026$writer) {\n    $writer-\u003eaddPrefix($prefix, $iri);\n};\n$parser = new TriGParser([\"format\" =\u003e \"trig\"], $tripleCallback, $prefixCallback);\n$parser-\u003eparseChunk($chunk);\n$parser-\u003eparseChunk($chunk);\n$parser-\u003eparseChunk($chunk);\n$parser-\u003eend(); //Needs to be called\n```\n\n#### Parser options\n\n* `format` input format (case-insensitive)\n  * if not provided or not matching any options below, then any [Turtle](https://www.w3.org/TR/turtle/), [TriG](https://www.w3.org/TR/trig/), [N-Triples](https://www.w3.org/TR/n-triples/) or [N-Quads](https://www.w3.org/TR/n-quads/) input can be parsed (but NOT the [N3](https://www.w3.org/TeamSubmission/n3/))\n  * `turtle` - [Turtle](https://www.w3.org/TR/turtle/)\n  * `trig` - [TriG](https://www.w3.org/TR/trig/)\n  * contains `triple`, e.g. `triple`, `ntriples`, `N-Triples` - [N-Triples](https://www.w3.org/TR/n-triples/)\n  * contains `quad`, e.g. `quad`, `nquads`, `N-Quads` - [N-Quads](https://www.w3.org/TR/n-quads/)\n  * contains `n3`, e.g. `n3` - [N3](https://www.w3.org/TeamSubmission/n3/)\n* `blankNodePrefix` (defaults to `b0_`) prefix forced on blank node names, e.g. `TriGWriter([\"blankNodePrefix\" =\u003e 'foo'])` will parse `_:bar` as `_:foobar`.\n* `documentIRI` sets the base URI used to resolve relative URIs (not applicable if `format` indicates n-triples or n-quads)\n* `lexer` allows usage of own lexer class. A lexer must provide following public methods:\n  * `tokenize(string $input, bool $finalize = true): array\u003carray{'subject': string, 'predicate': string, 'object': string, 'graph': string}\u003e`\n  * `tokenizeChunk(string $input): array\u003carray{'subject': string, 'predicate': string, 'object': string, 'graph': string}\u003e`\n  * `end(): array\u003carray{'subject': string, 'predicate': string, 'object': string, 'graph': string}\u003e`\n* `explicitQuantifiers` - [...]\n\n#### Empty document base IRI\n\nSome Turtle and N3 documents may use relative-to-the-base-IRI IRI syntax (see [here](https://www.w3.org/TR/turtle/#sec-iri) and [here](https://www.w3.org/TR/turtle/#sec-iri-references)), e.g.\n\n```\n\u003c\u003e \u003csomeProperty\u003e \"some value\" .\n```\n\nTo properly parse such documents the document base IRI must be known.\nOtherwise we might end up with empty IRIs (e.g. for the subject in the example above).\n\nSometimes the base IRI is encoded in the document, e.g.\n\n```\n@base \u003chttp://some.base/iri/\u003e .\n\u003c\u003e \u003csomeProperty\u003e \"some value\" .\n```\n\nbut sometimes it is missing.\nIn such a case the [Turtle specification](https://www.w3.org/TR/turtle/#in-html-parsing) requires us to follow section 5.1.1 of the [RFC3986](http://www.ietf.org/rfc/rfc3986.txt) which says that if the base IRI is not encapsulated in the document, it should be assumed to be the document retrieval URI (e.g. the URL you downloaded the document from or a file path converted to an URL). Unfortunatelly this can not be guessed by the hardf parser and has to be provided by you using the `documentIRI` parser creation option, e.g.\n\n```php\nparser = new TriGParser([\"documentIRI\" =\u003e \"http://some.base/iri/\"]);\n```\n\nLong story short if you run into the `subject/predicate/object on line X can not be parsed without knowing the the document base IRI.(...)` error, please initialize the parser with the `documentIRI` option.\n\n### Utility\n```php\nuse pietercolpaert\\hardf\\Util;\n```\n\nA static class with a couple of helpful functions for handling our specific triple representation. It will help you to create and evaluate literals, IRIs, and expand prefixes.\n\n```php\n$bool = isIRI($term);\n$bool = isLiteral($term);\n$bool = isBlank($term);\n$bool = isDefaultGraph($term);\n$bool = inDefaultGraph($triple);\n$value = getLiteralValue($literal);\n$literalType = getLiteralType($literal);\n$lang = getLiteralLanguage($literal);\n$bool = isPrefixedName($term);\n$expanded = expandPrefixedName($prefixedName, $prefixes);\n$iri = createIRI($iri);\n$literalObject = createLiteral($value, $modifier = null);\n```\n\nSee the documentation at https://github.com/RubenVerborgh/N3.js#utility for more information.\n\n## Two executables\n\nWe also offer 2 simple tools in `bin/` as an example implementation: one validator and one translator. Try for example:\n```bash\ncurl -H \"accept: application/trig\" http://fragments.dbpedia.org/2015/en | php bin/validator.php trig\ncurl -H \"accept: application/trig\" http://fragments.dbpedia.org/2015/en | php bin/convert.php trig n-triples\n```\n\n## Performance\n\nWe compared the performance on two turtle files, and parsed it with the EasyRDF library in PHP, the N3.js library for NodeJS and with Hardf. These were the results:\n\n| #triples | framework               | time (ms) | memory (MB) |\n|----------:|-------------------------|------:|--------:|\n|1,866    | __Hardf__ without opcache |  27.6   |   0.722     |\n|1,866    | __Hardf__ with opcache    |   24.5   |    0.380    |\n|1,866    | [EasyRDF](https://github.com/njh/easyrdf) without opcache |   5,166.5   |    2.772   |\n|1,866    | [EasyRDF](https://github.com/njh/easyrdf) with opcache    |  5,176.2    |  2.421     |\n|1,866    | [ARC2](https://github.com/semsol/arc2) with opcache | 71.9 | 1.966 |\n| 1,866  |   [N3.js](https://github.com/RubenVerborgh/N3.js) |  24.0    |  28.xxx  |\n| 3,896,560  |   __Hardf__ without opcache |  40,017.7    |  0.722   |\n| 3,896,560  |   __Hardf__ with opcache |    33,155.3  |    0.380   |\n| 3,896,560  |   [N3.js](https://github.com/RubenVerborgh/N3.js) |  7,004.0    |  59.xxx    |\n| 3,896,560  |  [ARC2](https://github.com/semsol/arc2) with opcache | 203,152.6 | 3,570.808  |\n\n## License, status and contributions\nThe hardf library is copyrighted by [Ruben Verborgh](http://ruben.verborgh.org/) and [Pieter Colpaert](https://pietercolpaert.be)\nand released under the [MIT License](https://github.com/pietercolpaert/hardf/blob/master/LICENSE).\n\nContributions are welcome, and bug reports or pull requests are always helpful.\nIf you plan to implement a larger feature, it's best to discuss this first by filing an issue.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpietercolpaert%2Fhardf","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpietercolpaert%2Fhardf","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpietercolpaert%2Fhardf/lists"}