Create Signposting from RO-Crate (#2)

* improvate jsonld parsing to be compatible with ro-crate

* refactoring

* example with RO-Crate

* bump version

---------

Co-authored-by: Daniel Bauer <daniel.bauer@senckenberg.de>
This commit is contained in:
Daniel Bauer
2024-11-21 15:40:46 +01:00
committed by GitHub
parent f97c33e418
commit 6b1ea1403c
8 changed files with 216 additions and 84 deletions

View File

@@ -1,14 +1,12 @@
from typing import Callable
from django.http import HttpRequest, HttpResponse
from signposting import Signpost, LinkRel
from signposting import Signpost
from bs4 import BeautifulSoup
import re
import json
from django.utils.deprecation import MiddlewareMixin
from django.conf import settings
from rdflib import Graph
from . import sparql
from .utils import jsonld_to_signposts
class SignpostingMiddleware:
@@ -45,68 +43,6 @@ class SignpostingMiddleware:
class JsonLdSignpostingParserMiddleware(MiddlewareMixin):
def is_url(self, url: str) -> bool:
url_pattern = re.compile(
r"^(https?|ftp)://" # protocol
r"(?:(?:[a-zA-Z0-9-_]+\.)?[a-zA-Z0-9-]+\.[a-zA-Z]{2,6})" # domain
r"(?::\d{1,5})?" # optional port
r"(?:/.*)?$" # path
)
return bool(url_pattern.match(url))
def select_url(self, elements: tuple[str, ...]) -> str | None:
for elem in elements[::-1]:
if self.is_url(str(elem)):
return str(elem)
return None
def _jsonld_to_signposts(self, jsonld: dict) -> dict:
signposts = []
# TODO use jsonld context in query as prefix
g = Graph().parse(data=json.dumps(jsonld), format="json-ld")
rootElement = next(iter(sparql.root_element_query(g)), None)
if rootElement:
rootElement = rootElement[0]
else:
print("No root element found")
return {}
types = sparql.type_query(g, rootElement)
for type in types:
signposts.append(Signpost(LinkRel.type, str(type[0])))
authors = sparql.author_query(g, rootElement)
for author in authors:
author = self.select_url(author)
if author:
signposts.append(Signpost(LinkRel.author, author))
license = next(iter(sparql.license_query(g, rootElement)), [])
license = self.select_url(license)
if license:
signposts.append(Signpost(LinkRel.license, license))
citations = sparql.cite_query(g, rootElement)
for citation in citations:
citation = self.select_url(citation)
if citation:
signposts.append(Signpost(LinkRel.cite_as, citation))
sameas = sparql.sameas_query(g, rootElement)
for sa in sameas:
sa_media_type = sa[-1]
sa = self.select_url(sa[:-1])
if sa:
signposts.append(Signpost(LinkRel.describedby, sa, sa_media_type))
items = sparql.item_query(g, rootElement)
for item in items:
item_media_type = item[-1]
item = self.select_url(item[:-1])
if item:
signposts.append(Signpost(LinkRel.item, item, item_media_type))
return signposts
def process_response(
self, request: HttpRequest, response: HttpResponse
@@ -119,7 +55,7 @@ class JsonLdSignpostingParserMiddleware(MiddlewareMixin):
for script in soup.find_all("script", type="application/ld+json"):
try:
jsonld = json.loads(script.string)
signposts = self._jsonld_to_signposts(jsonld)
signposts = jsonld_to_signposts(jsonld)
response._signposts = signposts
except json.JSONDecodeError as e: