hardf是一個 PHP 7.1+ 函式庫,可讓您處理連結資料 (RDF)。它提供:
解析器和序列化器都具有流支援。
該函式庫是 N3.js 到 PHP 的端口
我們在 PHP 中使用從 NodeJS N3.js 函式庫移植的三重表示。檢查 https://github.com/rdfjs/N3.js/tree/v0.10.0#triple-representation 以了解更多信息
我們有意關注效能,而不是開發人員友善性。因此,我們使用關聯數組而不是 PHP 物件來實現這種三重表示。因此,對於 N3.js 來說,現在是一個陣列。例如:
<?php
$ triple = [
' subject ' => ' http://example.org/cartoons#Tom ' ,
' predicate ' => ' http://www.w3.org/1999/02/22-rdf-syntax-ns#type ' ,
' object ' => ' http://example.org/cartoons#Cat ' ,
' graph ' => ' http://example.org/mycartoon ' , #optional
];
如下對文字進行編碼(類似 N3.js)
' "Tom"@en-gb ' // lowercase language
'" 1 "^^http: //www.w3.org/2001/XMLSchema#integer' // no angular brackets <>
使用 Composer 安裝此程式庫:
composer require pietercolpaert/ hardf
use pietercolpaert hardf TriGWriter ;
應該實例化的類,可以寫TriG或Turtle
使用範例:
$ writer = new TriGWriter ([
" prefixes " => [
" schema " => " http://schema.org/ " ,
" dct " => " http://purl.org/dc/terms/ " ,
" geo " => " http://www.w3.org/2003/01/geo/wgs84_pos# " ,
" rdf " => " http://www.w3.org/1999/02/22-rdf-syntax-ns# " ,
" rdfs " => " http://www.w3.org/2000/01/rdf-schema# "
],
" format " => " n-quads " //Other possible values: n-quads, trig or turtle
]);
$ writer -> addPrefix ( " ex " , " http://example.org/ " );
$ writer -> addTriple ( " schema:Person " , " dct:title " , "" Person " @en " , " http://example.org/#test " );
$ writer -> addTriple ( " schema:Person " , " schema:label " , "" Person " @en " , " http://example.org/#test " );
$ writer -> addTriple ( " ex:1 " , " dct:title " , "" Person1 " @en " , " http://example.org/#test " );
$ writer -> addTriple ( " ex:1 " , " http://www.w3.org/1999/02/22-rdf-syntax-ns#type " , " schema:Person " , " http://example.org/#test " );
$ writer -> addTriple ( " ex:2 " , " dct:title " , "" Person2 " @en " , " http://example.org/#test " );
$ writer -> addTriple ( " schema:Person " , " dct:title " , "" Person " @en " , " http://example.org/#test2 " );
echo $ writer -> end ();
//The method names should speak for themselves:
$ writer = new TriGWriter ([ " prefixes " : [ /* ... */ ]]);
$ writer -> addTriple ( $ subject , $ predicate , $ object , $ graphl );
$ writer -> addTriples ( $ triples );
$ writer -> addPrefix ( $ prefix , $ iri );
$ writer -> addPrefixes ( $ prefixes );
//Creates blank node($predicate and/or $object are optional)
$ writer -> blank ( $ predicate , $ object );
//Creates rdf:list with $elements
$ list = $ writer -> addList ( $ elements );
//Returns the current output it is already able to create and clear the internal memory use (useful for streaming)
$ out .= $ writer -> read ();
//Alternatively, you can listen for new chunks through a callback:
$ writer -> setReadCallback ( function ( $ output ) { echo $ output });
//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.
$ out .= $ writer -> end ();
//OR
$ writer -> end ();
除了 TriG 之外,TriGParser 類別還解析 Turtle、N-Triples、N-Quads 和 W3C 團隊提交 N3
$ parser = new TriGParser ( $ options , $ tripleCallback , $ prefixCallback );
$ parser -> setTripleCallback ( $ function );
$ parser -> setPrefixCallback ( $ function );
$ parser -> parse ( $ input , $ tripleCallback , $ prefixCallback );
$ parser -> parseChunk ( $ input );
$ parser -> end ();
使用返回值並將其傳遞給編寫器:
use pietercolpaert hardf TriGParser ;
use pietercolpaert hardf TriGWriter ;
$ parser = new TriGParser ([ " format " => " n-quads " ]); //also parser n-triples, n3, turtle and trig. Format is optional
$ writer = new TriGWriter ();
$ triples = $ parser -> parse ( " <A> <B> <C> <G> . " );
$ writer -> addTriples ( $ triples );
echo $ writer -> end ();
使用回調並將其傳遞給編寫器:
$ parser = new TriGParser ();
$ writer = new TriGWriter ([ " format " => " trig " ]);
$ parser -> parse ( " <http://A> <https://B> <http://C> <http://G> . <A2> <https://B2> <http://C2> <http://G3> . " , function ( $ e , $ triple ) use ( $ writer ) {
if (! isset ( $ e ) && isset ( $ triple )) {
$ writer -> addTriple ( $ triple );
echo $ writer -> read (); //write out what we have so far
} else if (! isset ( $ triple )) // flags the end of the file
echo $ writer -> end (); //write the end
else
echo " Error occured: " . $ e ;
});
當您需要解析大檔案時,您只需要解析區塊並已經處理它們。您可以按如下方式執行此操作:
$ writer = new TriGWriter ([ " format " => " n-quads " ]);
$ tripleCallback = function ( $ error , $ triple ) use ( $ writer ) {
if ( isset ( $ error ))
throw $ error ;
else if ( isset ( $ triple )) {
$ writer -> write ();
echo $ writer -> read ();
else if ( isset ( $ error )) {
throw $ error ;
} else {
echo $ writer -> end ();
}
};
$ prefixCallback = function ( $ prefix , $ iri ) use (& $ writer ) {
$ writer -> addPrefix ( $ prefix , $ iri );
};
$ parser = new TriGParser ([ " format " => " trig " ], $ tripleCallback , $ prefixCallback );
$ parser -> parseChunk ( $ chunk );
$ parser -> parseChunk ( $ chunk );
$ parser -> parseChunk ( $ chunk );
$ parser -> end (); //Needs to be called
format
輸入格式(不區分大小寫)turtle
- 烏龜trig
-TriGtriple
,例如triple
, ntriples
, N-Triples
- N-三元組quad
,例如quad
, nquads
, N-Quads
- N-Quadsn3
,例如n3
- N3blankNodePrefix
(預設為b0_
)強制在空白節點名稱上加上前綴,例如TriGWriter(["blankNodePrefix" => 'foo'])
會將_:bar
解析為_:foobar
。documentIRI
設定用於解析相對 URI 的基本 URI(如果format
指示 n-三元組或 n-四元組,則不適用)lexer
允許使用自己的詞法分析器類別。詞法分析器必須提供以下公共方法:tokenize(string $input, bool $finalize = true): array<array{'subject': string, 'predicate': string, 'object': string, 'graph': string}>
tokenizeChunk(string $input): array<array{'subject': string, 'predicate': string, 'object': string, 'graph': string}>
end(): array<array{'subject': string, 'predicate': string, 'object': string, 'graph': string}>
explicitQuantifiers
- [...] 一些 Turtle 和 N3 文件可能使用相對於基底 IRI 的 IRI 語法(請參閱此處和此處),例如
<> <someProperty> "some value" .
為了正確解析此類文檔,必須知道文檔基礎 IRI。否則,我們可能會得到空的 IRI(例如,對於上例中的主題)。
有時基本 IRI 會被編碼在文件中,例如
@base <http://some.base/iri/> .
<> <someProperty> "some value" .
但有時它會丟失。在這種情況下,Turtle 規格要求我們遵循 RFC3986 的第 5.1.1 節,其中規定如果基本 IRI 未封裝在文件中,則應假定它是文件檢索 URI(例如,您下載文件的 URL)來自或轉換為URL 的檔案路徑)。不幸的是, hardf解析器無法猜測這一點,並且必須由您使用documentIRI
解析器建立選項來提供,例如
parser = new TriGParser ([ " documentIRI " => " http://some.base/iri/ " ]);
長話短說, documentIRI
您subject/predicate/object on line X can not be parsed without knowing the the document base IRI.(...)
use pietercolpaert hardf Util ;
一個靜態類,帶有一些有用的函數,用於處理我們特定的三重表示。它將幫助您創建和評估文字、IRI 和擴展前綴。
$ bool = isIRI ( $ term );
$ bool = isLiteral ( $ term );
$ bool = isBlank ( $ term );
$ bool = isDefaultGraph ( $ term );
$ bool = inDefaultGraph ( $ triple );
$ value = getLiteralValue ( $ literal );
$ literalType = getLiteralType ( $ literal );
$ lang = getLiteralLanguage ( $ literal );
$ bool = isPrefixedName ( $ term );
$ expanded = expandPrefixedName ( $ prefixedName , $ prefixes );
$ iri = createIRI ( $ iri );
$ literalObject = createLiteral ( $ value , $ modifier = null );
有關更多信息,請參閱 https://github.com/RubenVerborgh/N3.js#utility 上的文檔。
我們還在bin/
中提供了 2 個簡單的工具作為範例實作:一個驗證器和一個翻譯器。嘗試例如:
curl -H " accept: application/trig " http://fragments.dbpedia.org/2015/en | php bin/validator.php trig
curl -H " accept: application/trig " http://fragments.dbpedia.org/2015/en | php bin/convert.php trig n-triples
我們比較了兩個海龜檔案的效能,並使用 PHP 中的 EasyRDF 函式庫、NodeJS 的 N3.js 函式庫以及hardf對其進行了解析。結果如下:
#三元組 | 框架 | 時間(毫秒) | 記憶體(MB) |
---|---|---|---|
1,866 | 沒有opcache的hardf | 27.6 | 0.722 |
1,866 | 帶有opcache的hardf | 24.5 | 0.380 |
1,866 | 沒有 opcache 的 EasyRDF | 5,166.5 | 2.772 |
1,866 | EasyRDF 與 opcache | 5,176.2 | 2.421 |
1,866 | 帶有 opcache 的 ARC2 | 71.9 | 1.966 |
1,866 | N3.js | 24.0 | 28.xxx |
3,896,560 | 沒有opcache的hardf | 40,017.7 | 0.722 |
3,896,560 | 帶有opcache的hardf | 33,155.3 | 0.380 |
3,896,560 | N3.js | 7,004.0 | 59.xxx |
3,896,560 | 帶有 opcache 的 ARC2 | 203,152.6 | 3,570.808 |
hardf庫的版權歸 Ruben Verborgh 和 Pieter Colpaert 所有,並根據 MIT 許可證發布。
歡迎貢獻,錯誤報告或拉取請求總是有幫助的。如果您計劃實現更大的功能,最好先透過提交問題來討論。