Jena常用指令

資訊來自Jena javadoc,我將比較常用的翻譯一下
如果沒翻譯的可能就是比較不重要的,或是我現在用不到的。

Model

  • add

    Model add(Resource s, Property p, RDFNode o)
    對目前的Model新增一個statement(triple)。
    Parameters:
    s - the subject of the statement to add
    p - the predicate of the statement to add
    o - the object of the statement to add
    Returns:
    this model
  • createProperty

    Property createProperty(String nameSpace, String localName)
    Create a property with a given URI composed from a namespace part and a localname part by concatenating the strings.This method may return an existing property with the correct URI and model, or it may construct a fresh one, as it sees fit.
    Subsequent operations on the returned property may modify this model.
    Parameters:
    nameSpace - Property的命名空間。
    localName - 你幫該property取的名字。
    Returns:
    a property instance

Resouce

  • addProperty

    Resource addProperty(Property p, String o)
    對Resource(subject or object)建立property與object,成立一個三元關係(triple)。
    Parameters:
    p - 欲新增之property。
    o - property(predicate)所連接的object。
    Returns:
    This resource to allow cascading calls.
  • getProperty

    Statement getProperty(Property p)
    回傳和目前這個resource相關的property與object,若property p是property q的子類別,也會被return。
    Parameters:
    p - 欲查詢之property。
    Returns:
    回傳和目前這個resource相關的property與object,若property p是property q的子類別,也會被return。沒有statement的話會回傳null。

Jena SPARQL

SPARQL是用來查詢RDF graph的一個語法。
RDF graph就是一大堆triple的組成
在Jena中所提到的model,也就是RDF graph,statement就是triples
RDF dataset中則包含了更多的graph

SPARQL設定方面

command Line的部分 使用cd C:\位址 跳槽
若發生JENA_HOME not set
就是環境變數沒有設定
1.先echo %PATH%,看看目前有沒有紀錄到
2.沒有的話入PATH=C:\Program Files\Java\(JDK資料夾)\bin;%PATH%
3.完成!!!!!!!!!!!!!

no query string or query file
bat\sparql.bat --data=vc-db-1.rdf --query=q1.rq
把兩個檔案放到同目錄就好了

基本用法

SELECT ?欄位
WHERE
  {
      條件(必須是triple)
  }

String Matching

{FILTER regex(?g, "r", "i") }  "r"是你想查詢的字串

Testing Values

SELECT ?resource
WHERE
  {
    ?resource info:age ?age .
    FILTER (?age >= 24)          使用FILTER(條件)
  }

OPTIONAL(IF)

SELECT ?name ?age
WHERE
{
    ?person vcard:FN  ?name .
    OPTIONAL { ?person info:age ?age }
}
!bound(?age) 這是一個unbound的動作,意即不符合結果的資料也會列出

在prefix前面有小老鼠的可能是n3格式,把rdf改成n3就可以解碼,如
@prefix foaf: <http://xmlns.com/foaf/0.1/> .

UNION

PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX vCard: <http://www.w3.org/2001/vcard-rdf/3.0#>

SELECT ?name
WHERE
{
   { [] foaf:name ?name } UNION { [] vCard:FN ?name }
}
其實sparql的語法很free,也可以修改成這樣
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX vCard: <http://www.w3.org/2001/vcard-rdf/3.0#>

SELECT ?name
WHERE
{
  [] ?p ?name
  FILTER ( ?p = foaf:name || ?p = vCard:FN )
}
如果把第一個例子的?name改成?name1與?name2,那結果可以更明顯的顯示
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX vCard: <http://www.w3.org/2001/vcard-rdf/3.0#>

SELECT ?name1 ?name2
WHERE
{
   { [] foaf:name ?name1 } UNION { [] vCard:FN ?name2 }
}

---------------------------------
| name1         | name2         |
=================================
| "Matt Jones"  |               |
| "Sarah Jones" |               |
|               | "Becky Smith" |
|               | "John Smith"  |
---------------------------------

Datasets

輸入sparql --help查看全部指令,可以看到 
Dataset
     --data=FILE            Data for the datset - triple or quad formats
     --graph=FILE           Graph for default graph of the datset(指定dataset中的預設graph)
     --namedGraph=FILE      Add a graph into the dataset as a named graph(對graph命名,並且加入dataset)
列出所有資料,語法sparql --graph ds-dft.ttl --namedgraph ds-ng-1.ttl --named graph ds-ng-2.ttl --query xxxxx.rq
PREFIX  xsd:    <http://www.w3.org/2001/XMLSchema#>
PREFIX  dc:     <http://purl.org/dc/elements/1.1/>
PREFIX  :       <.>

SELECT *
{
    { ?s ?p ?o } UNION { GRAPH ?g { ?s ?p ?o } }
}
另外用法,注意GRAPH後面一定要先留空格
PREFIX  xsd:    <http://www.w3.org/2001/XMLSchema#>
PREFIX  dc:     <http://purl.org/dc/elements/1.1/>
PREFIX  :       <.>

SELECT *
{
    { ?s ?p ?o } UNION { GRAPH :ds-ng-1.ttl { ?s ?p ?o } } 列出和ds-ng-1.ttl聯集資料
}
也可以把指令改寫成--query xxxxx.rq 只是要把FROM與FROM NAMED加入取代--graph與--namedgraph
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX dc:  <http://purl.org/dc/elements/1.1/>
PREFIX :    <.>

SELECT *
FROM       <ds-dft.ttl>
FROM NAMED <ds-ng-1.ttl>
FROM NAMED <ds-ng-2.ttl>
{
   { ?s ?p ?o } UNION { GRAPH ?g { ?s ?p ?o } }
}
也可以combo FILTER來使用
PREFIX  xsd:    <http://www.w3.org/2001/XMLSchema#>
PREFIX  dc:     <http://purl.org/dc/elements/1.1/>
PREFIX  :       <.>

SELECT ?date ?title
{
  ?g dc:date ?date . FILTER (?date > "2005-08-01T00:00:00Z"^^xsd:dateTime )
  GRAPH ?g
      { ?b dc:title ?title }
}

Manipulating SPARQL using ARQ

ARQ使用JAVA的方式來操作SPARQL(施工中)

References:


SPARQL Tutorial

Tutorial - Manipulating SPARQL using ARQ

Jena RDF Core API

Jena是使用Java編寫的API,可以用來做本體論的新增、查詢、修改與推論。

若還沒有建立Jena環境,可以參考如何在Eclipse中建立第一個Jena專案

以下在Jena中所提到的model、statement分別可以對應到RDF graph與triple。triple(statement)通常以名詞──動詞──名詞(主詞subject、謂詞predicate、受詞object)的方式表示,例如

Shakespear write Camelot

graph則是一大堆triple的集合。

簡單操作

1.建立Model
從ModelFactory中創造預設的Model
Model model = ModelFactory.createDefaultModel();

2.從Model中建立Resource
Resource johnSmith = model.createResource(personURI);

3.對resource增加property
//addProperty(Property p, RDFNode o)
johnSmith.addProperty(VCARD.FN, fullName);



把所有的triple列出來

1.使用Statement Iterator
StmtIterator iter = model.listStatements();

2.在while迴圈中建立Statement
Statement stmt      = iter.nextStatement(); 

3.抓出getter
Resource  subject   = stmt.getSubject();     // get the subject
Property  predicate = stmt.getPredicate();   // get the predicate
RDFNode   object    = stmt.getObject();      // get the object

4.也可以直接輸出XML格式
model.write(System.out);

Triple-annotation格式
model.write(System.out, "N-TRIPLES");

讀取rdf檔案

1.建立Model
Model model = ModelFactory.createDefaultModel();

2.使用FileManager打開檔案
 InputStream in = FileManager.get().open( inputFileName );

3.列印XML
model.read(in, null);
model.write(System.out);

P.S.:找不到vc-db-1.rdf? 放在和你放jena資料夾一樣的地方就好囉

設定前置命名空間

1.建立Model
Model model = ModelFactory.createDefaultModel();

2.設定前置
 String nsA = "http://somewhere/else#";
 String nsB = "http://nowhere/else#";

3.產生resources, properties,
 Resource root = m.createResource( nsA + "root" );//類似○,代表subject與object 
 Property P = m.createProperty( nsA + "P" );      //類似→,代表predicate
 Resource x = m.createResource( nsA + "x" );      //類似○,代表subject與object

4.將resource與property間的關係建立起來
 m.add( root, P, x );

5.查看結果
 m.write( System.out );

PS.:有沒有m.setNsPrefix的差異如下:
<j.1:P rdf:resource="http://somewhere/else#x"/> //no set
<nsA:P rdf:resource="http://somewhere/else#x"/> //set

m.read("location")
http://stackoverflow.com/questions/15782656/reading-local-owl-file-using-jena-response-filenotfoundexception

抽取URI

1.新增一個Resource, 存放等一下要retrive的resource
Resource vcard = model.getResource("http://somewhere/JohnSmith/");;

2.對Resource使用getProperty,把資料抽出來
String fullName = vcard.getProperty(VCARD.FN).getString();

PS.:這邊getString會直接輸出資料值,使用toString會輸出一整串XD

3.可以對取出的Resource增加資料
vcard.addProperty(VCARD.NICKNAME, "Smithy")

4.使用StmtIterator 來把所有的property列出來
StmtIterator iter = vcard.listProperties(VCARD.NICKNAME);

查詢Model

這邊是說如果什麼事情都用model.listStatement()來做也就太累了
1.所以使用ResIterator來代替Resource的查詢,找出有VCARD:FN屬性的資源
ResIterator iter = model.listSubjectsWithProperty(VCARD.FN);

2.進入if 迴圈 iter.hasNext print 
if (iter.hasNext()) {
    System.out.println("The database contains vcards for:");
    while (iter.hasNext()) {
        System.out.println("  " + iter.nextResource()
                                      .getProperty(VCARD.FN)
                                      .getString());
    }

有另外的方法,使用new SimpleSelector

1.再seletor中分別填入S, P, O
StmtIterator iter = model.listStatements(new SimpleSelector(null, VCARD.FN, (RDFNode) null)

操作Model

關於union, intersection與difference的操作
Model model = model1.union(model2);

容器(container)

關於容器,有三種,分別是BAG, ALT, SEQ
BAG是沒有規則隨便亂放的
ALT雖然也是沒有規則,但是基本上用來放替代品
SEQ是有規則的


Reference:

An Introduction to RDF and the Jena RDF API

使用PHP(1)

以下提供的教學資訊修改自書籍PHP and MySQL 24-Hour Trainer,僅供學術討論與交流使用。


暖身一下

既然要開始使用PHP,至少要先了解一下php環境的基本設置!
使用phpinfo()指令可以列出php環境的基本設置。
<?php phpinfo(); ?>


學習echo與include的用法


echo function可以用來顯示資料,大概就像Java的print、println一樣。
<h1>Welcome</h1>
<p>Today is Sep 27, 2011</p>

//上面輸出的結果和下面輸出的結果是一樣的

<h1>Welcome</h1>
<p>Today is <?php echo date('M j, Y'); ?></p>


include function 則可以讀取指定的檔案,並且將檔案的內容插入原本檔案的區塊之中。

<?php include ('yourFile.php'); ?>
如果還想了解更多的php function,可以查詢官方的php手冊


變數的使用與規則

在php中的變數是以錢錢的符號$呈現,在等號之後則是它對應的值。

<?php 

$myName = 'Andy';

?>

雖然值都是字串,但是使用單引號雙引號來quote會有不同的結果

<?php

$myName = 'Andy';

$myVar = "Hi, my name is $myName";

echo $myVar;

?>
<?php

$myName = 'Andy';

$myVar = 'Hi, my name is $myName';

echo $myVar;
?>

雙引號和單引號的差別在於雙引號可以解讀引號內的變數
單引號則是忠實呈現,即第二段程式碼echo出來的結果為

Hi, my name is $myName

有時候,使用複數形式可能會造成理解上的困難(這比較容易發生在英文裡)
這時候可以使用{}來強調、劃分變數(variables)。例如:

<?php

$Animal = 'cat';

$myVar = "5 {$Animal}s";

echo $myVar;

?>

括號中的字有包含引號的時候,要如何告訴電腦說其實引號不是用來運算的呢?
可以在引號前加入\ 進行逃跑(escape)~

<?php

$myVar = "I don\'t know what the hell is it.";

echo $myVar;

?>


文字與數字之間的轉換
在PHP中,若牽涉到數字的運算,字串會自動轉成數字,如以下的例子即為75
因為$stringNumber被轉換為15了

<?php

$stringNumber = '15a4';

$number = 5;

echo $stringNumber * $number;

?>

使用文字function例如htmlspecialchars() function可以保留html的符號顯示
文字與文字之間可以用句點(.)來concatenate(串連)。

程式碼除錯

當程式寫好之後,不一定能將資料顯示出來
而這些Bug通常都有常見的解決方案,可以先檢查一下:
  1. 是不是忘了打echo
  2. 大小寫的問題。PHP對於大小寫很敏感,也就是說變數的字母雖然一樣,但是若是大小寫不同,PHP會認為那是不同變數。
  3. 忘了打分號(;)
  4. =與==(==是等同數值)
  5. 忘了加$在變數前面,或是多加了$在function上
除此之外,可以善用die() function來讓程式碼的處理停留在某一行上,檢查到目前為止有無錯誤。


使用陣列

陣列是array function

$employee = array('Sally Meyers', 'George Smith', 'Peter Hengel');

使用echo來印出陣列中其中一個元素,0即是代表此陣列中第一個元素

echo $employee[0];

也可以直接指定陣列中的元素對應的數值

$employee[0] = 'Sally Meyers';

使用print_r() function 來列出陣列中所有元素,結果:

Array ( [0] => Sally Meyers [1] => George Smith [2] => Peter Hengel )


另外陣列也可以由以下的形式指定數值:

<?php

$employee = array('name'=>'Sally Meyers', 'position'=>'President', 'yearEmployed'=>2001 );



<?php

$employee['name'] = 'Sally Meyers';

$employee['position'] = 'President';

$employee['yearEmployed'] = 2001;

經過print_r() function列出

print_r($employee);

輸出結果:
Array ( [name] => Sally Meyers [position] => President [yearEmployed] => 2001 )

接著是陣列更複雜的形式
<?php

$employees = array(

array('name'=>'Sally Meyers', 'position'=>'President', 'yearEmployed'=>2001 ),

array('name'=>'George Smith', 'position'=>'Treasurer', 'yearEmployed'=>2006 ),

array('name'=>'Peter Hengel', 'position'=>'Clerk', 'yearEmployed'=>1992 ),

);

print_r($employees); 

輸出結果:
Array ( [0] => Array ( [name] => Sally Meyers [position] => President [yearEmployed] => 2001 ) [1] => Array ( [name] => George Smith [position] => Treasurer [yearEmployed] => 2006 ) [2] => Array ( [name] => Peter Hengel [position] => Clerk [yearEmployed] => 1992)


如果只想要顯示單一元素,就分別指定index來echo

echo $employees[0]['position'];


布林值(boolean)的echo


<?php

$myVar1 = true;

$myVar2 = false;

?>

<p>True:<?php echo $myVar1; ?></p>

<p>False:<?php echo $myVar2; ?></p>

上面這段程式碼的結果為

True:1
False:

False值是不包括任何東西的。在PHP的數值中,從不同的類型轉換到布林,以下狀況都將為False:
  1. 數字0 或是文字0
  2. 空字串 或是沒有元素的陣列
  3. 一個空值的變數
值得注意的是,如果你指定了$myVar = 'False'; PHP會當成你指定字串 所以返回的結果也是True



時間與日期


<?php

echo time();

結果會是millisecond的型態

1410414619


<?php

echo date('c') . '<br />';

echo date('m/d/Y') . '<br />';

echo date('l, F n, Y') . '<br />';

echo date('l ga') . '<br />';

echo date('h:i a') . '<br />';

結果

2014-09-11T07:51:11+02:00
09/11/2014
Thursday, September 9, 2014
Thursday 7am
07:51 am


若想要自行定義時間日期的顯示格式,可以查詢PHP: date - manualDate/Time Functions

使用mktime() function好處是可以做數學運算,並且顯示最終的時間

<?php

$offset = 16;

echo date('n/j/Y', mktime(0,0,0,12+$offset,5,2011));

結果
4/5/2013 

strtotime() function可以更方便的取得時間戳記

<?php

echo date('l, F j, Y', strtotime('12/5/2011')) . '<br />';

echo date('l, F j, Y', strtotime('yesterday', strtotime('12/5/2011'))) . '<br />';

echo date('l, F j, Y', strtotime('yesterday')) . '<br />';

echo date('l, F j, Y', strtotime('now')) . '<br />';

echo date('l, F j, Y', strtotime('Dec 5 2011')) . '<br />';

echo date('l, F j, Y', strtotime('+4 hours')) . '<br />';

echo date('l, F j, Y', strtotime('+1 week')) . '<br />';

echo date('l, F j, Y', strtotime('+2 weeks 1 day 4 hours 10 seconds')) . '<br />';

echo date('l, F j, Y', strtotime('next Tuesday')) . '<br />';

echo date('l, F j, Y', strtotime('last Monday'));

結果

Monday, December 5, 2011
Sunday, December 4, 2011
Wednesday, September 10, 2014
Thursday, September 11, 2014
Monday, December 5, 2011
Thursday, September 11, 2014
Thursday, September 18, 2014
Friday, September 26, 2014
Tuesday, September 16, 2014
Monday, September 8, 2014

getdate() function可以查詢目前時間陣列

Array ( [seconds] => 12 [minutes] => 6 [hours] => 8 [mday] => 11 [wday] => 4 [mon] => 9 [year] => 2014 [yday] => 253 [weekday] => Thursday [month] => September [0] => 1410415572 )

Reflection of Jena Documentation

Jena官方網站
An Introduction to RDF and the Jena RDF API
SPARQL Tutorial

Jena是一個用來開發語意網(Semantic Web)與連結資料(Linked Data)的Java API,支援對RDF的CRUD、查詢(Query)與推論(Inference)。

官方的教學中牽涉到幾種編碼與檔案格式,如RDF(S)N-Triple

RDF格式和HTML看起來差不多,只是它屬性的值前後都得以它的屬性名稱包裝起來:
<fruit>banana</fruit>

N-Triple直接顯示triple的關係,不像RDF呈現的方式那樣有階層的排序:
<http://.../monkey><http://.../eat><http://.../banana>

triple是以subject, predicate, object所組成,可以聯想成英文中的主詞、動詞與受詞。

Jena可以透過SPARQL來進行查詢,有兩種檔案格式:.rq & .n3
兩者最大的差別在於PREFIX前面有沒有加@,所以按照官方教學進行SPARQL指令出現錯誤時,可以試著修改檔案格式rq為n3試試看。