rdf-контейнеры - это, в общем, боль, довольно раздражающая в обращении с ними. Я публикую два решения, одно без SPARQL и другое с SPARQL. Лично я предпочитаю второй, тот, который использует SPARQL.
Пример 1: без SPARQL
Чтобы получить всех авторов для данной статьи, как в вашем случае, вы можете сделать
что-то вроде кода, который я публикую ниже.
Я добавил комментарии, так что это самоочевидно. Самый важный бит
это использование g.triple(triple_pattern)
с этой функцией графа в основном
Вы можете отфильтровать график rdflib и найти нужные вам тройные шаблоны.
Когда анализируется rdf: Seq, то предикаты в форме:
http://www.w3.org/1999/02/22-rdf-syntax-ns#_1
http://www.w3.org/1999/02/22-rdf-syntax-ns#_2
http://www.w3.org/1999/02/22-rdf-syntax-ns#_3
созданы, rdflib извлекает их в случайном порядке, поэтому вам нужно отсортировать их по
пройти их в правильном порядке.
import rdflib
RDF = rdflib.namespace.RDF
#Parse the file
g = rdflib.Graph()
g.parse("zot.rdf")
#So that we are sure we get something back
print "Number of triples",len(g)
#Couple of handy namespaces to use later
BIB = rdflib.Namespace("http://purl.org/net/biblio#")
FOAF = rdflib.Namespace("http://xmlns.com/foaf/0.1/")
#Author counter to print at the bottom
i=0
#Article for wich we want the list of authors
article = rdflib.term.URIRef("http://www.ncbi.nlm.nih.gov/pubmed/18273724")
#First loop filters is equivalent to "get all authors for article x"
for triple in g.triples((article,BIB["authors"],None)):
#This expresions removes the rdf:type predicate cause we only want the bnodes
# of the form http://www.w3.org/1999/02/22-rdf-syntax-ns#_SEQ_NUMBER
# where SEQ_NUMBER is the index of the element in the rdf:Seq
list_triples = filter(lambda y: RDF['type'] != y[1], g.triples((triple[2],None,None)))
#We sort the authors by the predicate of the triple - order in sequences do matter ;-)
# so "http://www.w3.org/1999/02/22-rdf-syntax-ns#_435"[44:] returns 435
# and since we want numberic order we do int(x[1][44:]) - (BTW x[1] is the predicate)
authors_sorted = sorted(list_triples,key=lambda x: int(x[1][44:]))
#We iterate the authors bNodes and we get surname and givenname
for author_bnode in authors_sorted:
for x in g.triples((author_bnode[2],FOAF['surname'],None)):
author_surname = x[2]
for y in g.triples((author_bnode[2],FOAF['givenname'],None)):
author_name = y[2]
print "author(%s): %s %s"%(i,author_name,author_surname)
i += 1
В этом примере показано, как это сделать без использования SPARQL.
Пример 2: с SPARQL
Теперь есть точно такой же пример, но с использованием SPARQL.
rdflib.plugin.register('sparql', rdflib.query.Processor,
'rdfextras.sparql.processor', 'Processor')
rdflib.plugin.register('sparql', rdflib.query.Result,
'rdfextras.sparql.query', 'SPARQLQueryResult')
query = """
SELECT ?seq_index ?name ?surname WHERE {
<http://www.ncbi.nlm.nih.gov/pubmed/18273724> bib:authors ?seq .
?seq ?seq_index ?seq_bnode .
?seq_bnode foaf:givenname ?name .
?seq_bnode foaf:surname ?surname .
}
"""
for row in sorted(g.query(query, initNs=dict(rdf=RDF,foaf=FOAF,bib=BIB)),
key=lambda x:int(x[0][44:])):
print "Author(%s) %s %s"%(row[0][44:],row[1],row[2])
Как видно, нам все еще нужно выполнить сортировку, потому что библиотека сама не справляется с этим. В запросе переменная seq_index
содержит предикат, который содержит информацию о порядке следования и который выполняет сортировку в лямбда-функции.