├── lxltools ├── __init__.py ├── timeutil.py ├── ldutil.py └── lxlslug.py ├── .python-version ├── requirements.txt ├── examples ├── queries │ ├── select_labels.rq │ ├── select-wikidata-languages.rq │ ├── select_missing_domainrange.rq │ └── select_missing_domainrange_datatypeprop.rq ├── mappings │ ├── services.ttl │ ├── misc-skos-mappings.ttl │ ├── libris-uri-scheme.ttl │ └── bibframe-identifiers.ttl └── context.jsonld ├── sys └── context │ ├── keywords.jsonld │ ├── ns.jsonld │ ├── target │ ├── sdo-w3c.jsonld │ ├── bibo-w3c.jsonld │ └── loc-w3c-sdo.jsonld │ ├── base.jsonld │ └── shared.jsonld ├── source ├── doc │ ├── model.en.mkd │ ├── summary.sv.mkd │ ├── issues │ │ ├── literal-structures.en.mkd │ │ ├── record-thing.en.mkd │ │ └── concept-thing.en.mkd │ ├── about.sv.mkd │ ├── standards.en.mkd │ ├── services.en.mkd │ ├── philosophy.en.mkd │ └── issues.en.mkd ├── update-enums.rq ├── swepub │ ├── update.rq │ ├── vocab.ttl │ ├── types.ttl │ └── terms.ttl ├── datasets │ ├── sab.ttl │ ├── syscore.ttl │ ├── i18n.ttl │ ├── signe.ttl │ ├── bibdb.ttl │ └── external.ttl ├── remote │ ├── construct-bnf-roles.rq │ ├── construct-matching-wd-labels.rq │ └── construct-aat-materials.rq ├── identifiers.ttl ├── i18n │ ├── collections.ttl │ └── rules.ttl ├── construct-tacnotationterms.rq ├── construct-musnotationsterms.rq ├── repr-terms.ttl ├── vocab │ ├── updateResource.rq │ ├── external-labels.ttl │ ├── update.rq │ ├── check-bases.rq │ ├── libris-search-experimental.ttl │ ├── bf-map.ttl │ ├── bf-to-kbv-base.rq │ ├── accessibility.ttl │ └── files-packages-representations.ttl ├── construct-materials.rq ├── construct-countries.rq ├── construct-rda-terms.rq ├── construct-cc-license-data.rq ├── cc-licenses-header.txt ├── kbv-enums.ttl ├── bibliographies.jsonld ├── construct-relators.rq ├── construct-languages-iso639-1.rq ├── marc │ └── base.ttl ├── construct-languages-iso639-2.rq ├── generators.ttl ├── movementnotation.ttl ├── tactilenotation.ttl ├── changecategories.ttl ├── musicnotation.ttl ├── containers.ttl ├── policies.ttl ├── app │ └── help.jsonld ├── encodingFormat-terms.ttl └── bibdb │ └── terms.ttl ├── scripts ├── misc │ ├── convert-marcxml-to-bibframe.sh │ ├── jsontr.py │ └── mk-graph-data.py ├── make-lexical-rda.rq ├── construct.py ├── vocab-update-unstable.rq ├── vocab-update-cleanup.rq ├── make-lexical-rda.py ├── map-mads-from-skos.rq ├── checkdisplay.py ├── marc │ ├── README.md │ ├── describe_marcmap.py │ ├── frbrize_marcmap.py │ └── marcmap-tokenmaps.json ├── get-proxy-domains-ranges.rq ├── load-defs-whelk.sh ├── analyze-enums.py ├── extract-marcframe-terms.py ├── marcframe-skeleton-from-bibframe.py ├── create_sab_skos_data.py ├── digest-marcframe.py ├── get-model-terms-from-example-usage.py ├── make_rda_mappings.py └── create_i18n_datasets.py ├── pyproject.toml ├── .gitignore ├── common.py ├── query.py ├── datasets.py ├── docs.py ├── bibdb_datasets.py ├── Makefile └── syscore.py /lxltools/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.python-version: -------------------------------------------------------------------------------- 1 | pypy-3.11 2 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | setuptools==70.0.0 2 | rdflib==6.1.1 3 | pyRdfa3==3.5.3 4 | requests==2.32.3 5 | Markdown==3.7 6 | -------------------------------------------------------------------------------- /examples/queries/select_labels.rq: -------------------------------------------------------------------------------- 1 | prefix rdfs: 2 | 3 | select * { 4 | ?s rdfs:label ?label . 5 | } 6 | 7 | -------------------------------------------------------------------------------- /sys/context/keywords.jsonld: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "type": "@type", 4 | "id": "@id", 5 | "lang": "@language", 6 | "val": "@value", 7 | "dt": "@datatype" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /source/doc/model.en.mkd: -------------------------------------------------------------------------------- 1 | Data Model 2 | =========== 3 | 4 | The description of the data model has been been relocated to [https://github.com/libris/definitions/wiki/Data-Model](https://github.com/libris/definitions/wiki/Data-Model). -------------------------------------------------------------------------------- /scripts/misc/convert-marcxml-to-bibframe.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | SAXON_JAR=$1 3 | QUERY=$2 4 | SOURCE=$(pwd)/$3 5 | 6 | BASE=http://libris.kb.se/bib/ 7 | java -cp $SAXON_JAR net.sf.saxon.Query $QUERY marcxmluri=$SOURCE baseuri=$BASE serialization=rdfxml 8 | -------------------------------------------------------------------------------- /source/update-enums.rq: -------------------------------------------------------------------------------- 1 | prefix skos: 2 | prefix : 3 | 4 | insert { 5 | ?coll skos:member ?term . 6 | } where { 7 | ?coll a :CollectionClass . 8 | ?term a ?coll . 9 | } 10 | -------------------------------------------------------------------------------- /source/swepub/update.rq: -------------------------------------------------------------------------------- 1 | prefix swe: 2 | prefix skos: 3 | 4 | insert { 5 | ?term skos:inScheme 6 | } where { 7 | ?term ?p ?o 8 | filter ((?term != swe:) && strstarts(str(?term), str(swe:))) 9 | }; -------------------------------------------------------------------------------- /examples/mappings/services.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | @prefix hydra: . 3 | 4 | :Library hydra:search [ 5 | hydra:template "https://bibdb.libris.kb.se/api/library" ; 6 | hydra:mapping [ hydra:property :sigel; hydra:variable "sigel" ] 7 | ] . 8 | -------------------------------------------------------------------------------- /source/datasets/sab.ttl: -------------------------------------------------------------------------------- 1 | prefix xsd: 2 | prefix : 3 | base 4 | 5 | a :Dataset ; 6 | :sourceData [ :uri "source/sab.ttl" ] ; 7 | :uriSpace "/term/sab/" ; 8 | :created "2014-01-23T10:34:17.981Z"^^xsd:dateTime . 9 | -------------------------------------------------------------------------------- /source/remote/construct-bnf-roles.rq: -------------------------------------------------------------------------------- 1 | prefix skos: 2 | 3 | construct { 4 | ?role ?p ?o 5 | } where { 6 | service { 7 | ?role skos:inScheme ; 8 | ?p ?o . 9 | } 10 | } 11 | 12 | -------------------------------------------------------------------------------- /source/doc/summary.sv.mkd: -------------------------------------------------------------------------------- 1 | **id.kb.se** är en tjänst som tillgängliggör de grundstenar Kungliga biblioteket använder för att publicera strukturerade, [länkade data](https://sv.wikipedia.org/wiki/L%C3%A4nkad_data). Här finns gemensamma definitioner och begrepp som hjälper till att samordna beskrivningar av vårt material. 2 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "definitions" 3 | version = "0.1.0" # This is currently a fixed dummy version. 4 | readme = "README.md" 5 | requires-python = ">=3.9" 6 | dependencies = [ 7 | "markdown==3.7", 8 | "pyrdfa3==3.5.3", 9 | "rdflib==6.1.1", 10 | "requests==2.32.3", 11 | "setuptools==70.0.0", 12 | ] 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Cached Data and Packages 2 | /cache 3 | /viewer/node_modules 4 | /viewer/bower_components 5 | 6 | # Generated Files 7 | /build 8 | /viewer/static/build 9 | /viewer/tests/bin 10 | /viewer/static/vendor 11 | /logs 12 | 13 | # Local App Config 14 | /.venv 15 | /venv 16 | 17 | # Common OS, Tool and Editor Files 18 | .*.sw* 19 | .DS_Store 20 | npm-debug.log 21 | *.pyc 22 | .idea/ 23 | -------------------------------------------------------------------------------- /scripts/make-lexical-rda.rq: -------------------------------------------------------------------------------- 1 | prefix owl: 2 | prefix reg: 3 | 4 | construct { 5 | ?alias owl:sameAs ?s ; ?p ?bound_o . 6 | } where { 7 | ?s ?p ?o . 8 | FILTER(?p != reg:lexicalAlias) 9 | ?s reg:lexicalAlias ?alias . 10 | OPTIONAL { ?o reg:lexicalAlias ?alias_o . } 11 | BIND(COALESCE(?alias_o, ?o) as ?bound_o) 12 | } 13 | -------------------------------------------------------------------------------- /source/identifiers.ttl: -------------------------------------------------------------------------------- 1 | @prefix skos: . 2 | 3 | @base . # TODO: base /alias/ ? 4 | 5 | # Aliases for externally defined 6 | @base . 7 | skos:notation "ISSN" . 8 | skos:notation "ISBN" . 9 | skos:notation "EAN" . 10 | skos:notation "URN" . 11 | skos:notation "SB17" . 12 | skos:notation "TPB" . 13 | skos:notation "DOI" . 14 | -------------------------------------------------------------------------------- /source/remote/construct-matching-wd-labels.rq: -------------------------------------------------------------------------------- 1 | prefix : 2 | prefix rdfs: 3 | prefix skos: 4 | 5 | construct { 6 | ?script :exactMatch ?match ; :prefLabel ?label . 7 | } where { 8 | ?script a :Script ; :exactMatch ?match . 9 | service { 10 | ?match (skos:prefLabel|rdfs:label) ?label . 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /sys/context/ns.jsonld: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#", 4 | "rdfs": "http://www.w3.org/2000/01/rdf-schema#", 5 | "owl": "http://www.w3.org/2002/07/owl#", 6 | "skos": "http://www.w3.org/2004/02/skos/core#", 7 | "xsd": "http://www.w3.org/2001/XMLSchema#", 8 | "dc": "http://purl.org/dc/terms/", 9 | "schema": "http://schema.org/", 10 | "kbv": "https://id.kb.se/vocab/" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /source/i18n/collections.ttl: -------------------------------------------------------------------------------- 1 | prefix : 2 | base 3 | 4 | a :TermCollection ; 5 | :label "Libris urval av translittereringsregler"@sv, "Libris selection of transliteration rules"@en ; 6 | :collectionItem , 7 | , 8 | , 9 | , 10 | . 11 | -------------------------------------------------------------------------------- /source/remote/construct-aat-materials.rq: -------------------------------------------------------------------------------- 1 | prefix aat: 2 | prefix gvp: 3 | prefix skos: 4 | 5 | construct { 6 | ?material skos:prefLabel ?prefLabel 7 | } where { 8 | service { 9 | ?material gvp:broaderExtended aat:300010357 ; # belongs to the materials hierarchy 10 | skos:prefLabel ?prefLabel . 11 | } 12 | } -------------------------------------------------------------------------------- /examples/queries/select-wikidata-languages.rq: -------------------------------------------------------------------------------- 1 | ## 2 | # Example invocation: 3 | # $ curl -Haccept:text/csv -s https://query.wikidata.org/sparql --data-urlencode "query=$(cat $THIS_FILE)" 4 | 5 | prefix rdfs: 6 | prefix wd: 7 | prefix wdt: 8 | 9 | select ?id ?code ?label { 10 | ?id wdt:P31 wd:Q34770 ; 11 | wdt:P220 ?code ; 12 | rdfs:label ?label . 13 | } 14 | -------------------------------------------------------------------------------- /sys/context/target/sdo-w3c.jsonld: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | {"@vocab": "http://schema.org/"}, 4 | {"ldp": "http://www.w3.org/ns/ldp#"}, 5 | {"skos": "http://www.w3.org/2004/02/skos/core#"}, 6 | {"prov": "http://www.w3.org/ns/prov#"}, 7 | {"owl": "http://www.w3.org/2002/07/owl#"}, 8 | {"rdfs": "http://www.w3.org/2000/01/rdf-schema#"}, 9 | {"rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#"}, 10 | {"xsd": "http://www.w3.org/2001/XMLSchema#"} 11 | ], 12 | "created": "2021-10-18T13:47:49.626Z" 13 | } 14 | -------------------------------------------------------------------------------- /common.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from lxltools.datacompiler import Compiler 4 | 5 | compiler = Compiler( 6 | base_dir=os.path.dirname(__file__), 7 | datasets_description="source/datasets/idkbse.ttl", 8 | dataset_id="https://id.kb.se/dataset/common", 9 | created="2013-10-17T14:07:48.000Z", 10 | tool_id="https://id.kb.se/generator/datasetcompiler", 11 | context="sys/context/base.jsonld", 12 | system_base_iri="", 13 | union="common.jsonld.lines", 14 | ) 15 | 16 | if __name__ == "__main__": 17 | compiler.main() 18 | -------------------------------------------------------------------------------- /scripts/construct.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import sys 3 | 4 | from rdflib import ConjunctiveGraph 5 | from rdflib.plugin import Parser, register 6 | 7 | register("text/html", Parser, "pyRdfa.rdflibparsers", "RDFaParser") 8 | 9 | queryfile, *infiles = sys.argv[1:] 10 | 11 | cg = ConjunctiveGraph() 12 | for infile in infiles: 13 | cg.parse(infile) 14 | 15 | with open(queryfile) as f: 16 | res = cg.query(f.read()) 17 | 18 | res.graph.namespace_manager = cg.namespace_manager 19 | res.serialize(sys.stdout.buffer, format='turtle') 20 | -------------------------------------------------------------------------------- /scripts/vocab-update-unstable.rq: -------------------------------------------------------------------------------- 1 | PREFIX owl: 2 | PREFIX vs: 3 | 4 | 5 | INSERT { 6 | ?term vs:term_status "unstable" 7 | } WHERE { 8 | { 9 | ?term a owl:Class 10 | FILTER NOT EXISTS { ?term owl:equivalentClass ?eqc } 11 | } UNION { 12 | { 13 | ?term a owl:ObjectProperty 14 | } UNION { 15 | ?term a owl:DatatypeProperty 16 | } 17 | FILTER NOT EXISTS { ?term owl:equivalentProperty ?eqp } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /examples/queries/select_missing_domainrange.rq: -------------------------------------------------------------------------------- 1 | prefix rdfs: 2 | prefix owl: 3 | prefix sdo: 4 | 5 | select distinct ?s ?domain ?range { 6 | { 7 | ?s a owl:DatatypeProperty 8 | } union { 9 | ?s a owl:ObjectProperty 10 | } 11 | optional { 12 | ?s (rdfs:domain|sdo:domainIncludes) ?domain . 13 | } 14 | optional { 15 | ?s (rdfs:range|sdo:rangeIncludes) ?range . 16 | } 17 | filter(!bound(?domain) || !bound(?range)) 18 | } 19 | 20 | -------------------------------------------------------------------------------- /scripts/vocab-update-cleanup.rq: -------------------------------------------------------------------------------- 1 | PREFIX owl: 2 | PREFIX dbpo: 3 | PREFIX sdo: 4 | PREFIX : 5 | 6 | DELETE DATA { 7 | 8 | :influencedBy owl:equivalentProperty dbpo:influencedBy . 9 | 10 | :title owl:equivalentProperty sdo:title . 11 | :sameAs owl:equivalentProperty sdo:sameAs . 12 | :comment owl:equivalentProperty sdo:comment . 13 | :source owl:equivalentProperty sdo:source . 14 | 15 | :Unspecified a owl:Class; rdfs:subClassOf :Product . 16 | 17 | } 18 | -------------------------------------------------------------------------------- /examples/context.jsonld: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | { 4 | "@vocab": "http://schema.org/", 5 | "dc": "http://purl.org/dc/terms/", 6 | "rdael": "http://rdvocab.info/Elements/", 7 | "title": {"@id": "dc:title", "@language": "sv"}, 8 | "responsibilityStatement": {"@id": "rdael:statementOfResponsibility", "@language": "sv"}, 9 | "description": {"@language": "sv"}, 10 | "dateCreated": {"@type": "Date"}, 11 | "datePublished": {"@type": "Date"}, 12 | "startDate": {"@type": "Date"}, 13 | "endDate": {"@type": "Date"} 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /source/datasets/syscore.ttl: -------------------------------------------------------------------------------- 1 | prefix : 2 | prefix xsd: 3 | base 4 | 5 | a :Dataset ; 6 | :sameAs ; 7 | :inDataCatalog ; 8 | :publisher ; 9 | :label "The Dataset of all Libris Datasets"@en . 10 | 11 | a :Dataset ; 12 | :isPartOf ; 13 | :created "2022-11-19T13:09:35.010Z"^^xsd:dateTime ; 14 | :sourceData [ :uri "build/syscore.jsonld.lines" ; 15 | :sourceData [ :tool ] ] . 16 | -------------------------------------------------------------------------------- /source/construct-tacnotationterms.rq: -------------------------------------------------------------------------------- 1 | prefix skos: 2 | 3 | construct { 4 | ?s ?p ?o ; 5 | skos:prefLabel ?prefLabel ; 6 | skos:definition ?definition . 7 | } where { 8 | graph { 9 | ?s ?p ?o ; skos:exactMatch ?rda . 10 | optional { 11 | graph { 12 | ?rda skos:prefLabel ?prefLabel ; 13 | skos:definition ?definition . 14 | filter(lang(?prefLabel) != 'sv') 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /source/construct-musnotationsterms.rq: -------------------------------------------------------------------------------- 1 | prefix skos: 2 | 3 | construct { 4 | ?s ?p ?o ; 5 | skos:prefLabel ?prefLabel ; 6 | skos:definition ?definition . 7 | } where { 8 | graph { 9 | ?s ?p ?o ; skos:exactMatch ?rda . 10 | optional { 11 | graph { 12 | ?rda skos:prefLabel ?prefLabel ; 13 | skos:definition ?definition . 14 | filter(lang(?prefLabel) != 'sv') 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /scripts/make-lexical-rda.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from rdflib import Graph 3 | from os import path as P 4 | import sys 5 | 6 | RDA_SOURCE_NAMES = ['a', 'c', 'w', 'e', 'm', 'i', 'z'] 7 | 8 | g = Graph() 9 | 10 | for name in RDA_SOURCE_NAMES: 11 | g.parse("http://rdaregistry.info/Elements/{}.ttl".format(name), format='turtle') 12 | 13 | with open(P.join(P.dirname(__file__), 'make-lexical-rda.rq')) as fp: 14 | res = g.query(fp) 15 | 16 | for name in RDA_SOURCE_NAMES: 17 | res.graph.namespace_manager.bind(name, 18 | "http://rdaregistry.info/Elements/{}/".format(name)) 19 | 20 | res.graph.serialize(sys.stdout, format='turtle') 21 | -------------------------------------------------------------------------------- /scripts/map-mads-from-skos.rq: -------------------------------------------------------------------------------- 1 | prefix rdfs: 2 | prefix owl: 3 | prefix skos: 4 | prefix madsrdf: 5 | 6 | construct { 7 | 8 | ?term owl:equivalentProperty ?madsterm . 9 | 10 | } where { 11 | 12 | ?term owl:equivalentProperty ?skosterm . 13 | 14 | FILTER(!strstarts(str(?term), str(skos:))) 15 | FILTER(!strstarts(str(?term), str(madsrdf:))) 16 | 17 | ?madsterm rdfs:subPropertyOf ?skosterm . 18 | FILTER(!strstarts(str(?madsterm), str(skos:)) 19 | && strstarts(str(?skosterm), str(skos:))) 20 | 21 | } 22 | -------------------------------------------------------------------------------- /scripts/checkdisplay.py: -------------------------------------------------------------------------------- 1 | import json 2 | from pathlib import Path 3 | 4 | project_dir = Path(__file__).parent.parent 5 | displaypath = project_dir / "source/vocab/display.jsonld" 6 | 7 | with displaypath.open() as f: 8 | display = json.load(f) 9 | 10 | for group in display["lensGroups"].values(): 11 | if g_id := group.get("@id"): 12 | print(g_id) 13 | for key, lens in group.get("lenses", {}).items(): 14 | cld = lens.get("classLensDomain") 15 | if key != cld: 16 | if cld is None: 17 | print(f" {key} - Missing classLensDomain") 18 | else: 19 | print(f" {key} - Different classLensDomain: {cld}") 20 | print() 21 | -------------------------------------------------------------------------------- /sys/context/target/bibo-w3c.jsonld: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | {"bibo": "http://purl.org/ontology/bibo/"}, 4 | {"skos": "http://www.w3.org/2004/02/skos/core#"}, 5 | {"dc": "http://purl.org/dc/terms/"}, 6 | {"dctype": "http://purl.org/dc/dcmitype/"}, 7 | {"prov": "http://www.w3.org/ns/prov#"}, 8 | {"foaf": "http://xmlns.com/foaf/0.1/"}, 9 | {"void": "http://rdfs.org/ns/void#"}, 10 | {"owl": "http://www.w3.org/2002/07/owl#"}, 11 | {"rdfs": "http://www.w3.org/2000/01/rdf-schema#"}, 12 | {"rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#"}, 13 | {"xsd": "http://www.w3.org/2001/XMLSchema#"}, 14 | {"ldp": "http://www.w3.org/ns/ldp#"} 15 | ], 16 | "created": "2021-10-18T14:18:25.440Z" 17 | } 18 | -------------------------------------------------------------------------------- /examples/queries/select_missing_domainrange_datatypeprop.rq: -------------------------------------------------------------------------------- 1 | prefix rdfs: 2 | prefix owl: 3 | prefix sdo: 4 | 5 | select distinct ?s ?domain ?range { 6 | { 7 | ?s a owl:DatatypeProperty 8 | optional { 9 | ?s (rdfs:domain|sdo:domainIncludes) ?domain . 10 | } 11 | filter(!bound(?domain)) 12 | } 13 | union 14 | { 15 | ?s a owl:ObjectProperty 16 | optional { 17 | ?s (rdfs:domain|sdo:domainIncludes) ?domain . 18 | } 19 | optional { 20 | ?s (rdfs:range|sdo:rangeIncludes) ?range . 21 | } 22 | filter(!bound(?domain) || !bound(?range)) 23 | } 24 | } 25 | order by asc(?s) 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /source/repr-terms.ttl: -------------------------------------------------------------------------------- 1 | @prefix rdfs: . 2 | @prefix owl: . 3 | @prefix sdo: . 4 | @prefix skos: . 5 | @prefix : . 6 | @prefix aat: . 7 | @base . #TODO term till enums? 8 | 9 | 10 | a :GenreForm ; 11 | skos:prefLabel "Page"@en, "Sida"@sv ; 12 | skos:inScheme ; #TODO term till enums? 13 | skos:closeMatch aat:300194222 . 14 | 15 | a :GenreForm ; 16 | skos:prefLabel "Issue"@en, "Upplaga"@sv ; 17 | skos:inScheme ; #TODO term till enums? 18 | skos:closeMatch aat:300312349 . 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /examples/mappings/misc-skos-mappings.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | @prefix sab: . 3 | @prefix bicssc: . 4 | 5 | sab:Lz a :Concept; 6 | :notation "Lz"; 7 | :exactMatch . 8 | 9 | bicssc:FH a :Concept; 10 | :notation "FH"; 11 | :exactMatch . 12 | 13 | bicssc:FK a :Concept; 14 | :notation "FK"; 15 | :exactMatch . 16 | 17 | bicssc:FL a :Concept; 18 | :notation "FL"; 19 | :exactMatch . 20 | 21 | bicssc:FM a :Concept; 22 | :notation "FM"; 23 | :exactMatch . 24 | 25 | -------------------------------------------------------------------------------- /source/doc/issues/literal-structures.en.mkd: -------------------------------------------------------------------------------- 1 | # Literal Structures 2 | 3 | ## The Use of Language 4 | 5 | Compare uses of Language Tags with presence of bf:descriptionLanguage, and also possible interpretations of language of a Work or Concept for determining language of plain strings in the title or prefLabel. 6 | 7 | ## Extended Literals (SKOS-XL) as Structured Values 8 | 9 | To represent transliterated forms. To be decided. 10 | 11 | ### Literals and Structured Values 12 | 13 | .. Error-correct untyped strings (vs. keeping differently cast terms in JSON-LD) 14 | 15 | .. Soft-match partial datatype values (dates... 16 | 17 | .. turn into rdf:value + :year, :month, :day? (as "virtual" properties of a Datatype) 18 | .. Shrink to Datatype Literals 19 | 20 | .. Interpret Labels and Annotations (c.f. schema:PropertyValue) 21 | -------------------------------------------------------------------------------- /source/vocab/updateResource.rq: -------------------------------------------------------------------------------- 1 | prefix rdfs: 2 | prefix owl: 3 | prefix : 4 | 5 | insert { 6 | ?term rdfs:subClassOf :Resource 7 | 8 | } where { 9 | ?term a owl:Class 10 | 11 | # Add Resource where subClassOf is missing (Is this part redundant? Enough with the minus clause?) 12 | optional {?term rdfs:subClassOf ?subClassOf} 13 | filter(!bound(?subClassOf)) 14 | 15 | # Don't add subClassOf if term already is :Resource 16 | filter(?term != :Resource) 17 | 18 | # Don't add if ?subClassOf contains refs that starts with 19 | MINUS { 20 | ?term rdfs:subClassOf ?baseClassUri 21 | filter ((?baseClassUri != :) && strstarts(str(?baseClassUri), str(:))) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /source/construct-materials.rq: -------------------------------------------------------------------------------- 1 | prefix skos: 2 | 3 | construct { 4 | ?s ?p ?o ; 5 | skos:prefLabel ?prefLabel ; 6 | skos:definition ?definition . 7 | } where { 8 | graph { 9 | ?s ?p ?o . 10 | optional { 11 | ?s skos:exactMatch ?aat . 12 | graph { 13 | ?aat skos:prefLabel ?aatLabel . 14 | } 15 | } 16 | optional { 17 | ?s skos:exactMatch ?rda . 18 | graph { 19 | ?rda skos:prefLabel ?rdaLabel ; 20 | skos:definition ?definition . 21 | } 22 | } 23 | bind(coalesce(?rdaLabel, ?aatLabel) as ?prefLabel) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /query.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals, print_function 2 | from rdflib import ConjunctiveGraph 3 | from rdflib.util import guess_format 4 | 5 | 6 | def run_query(source, query_file, context=None): 7 | graph = ConjunctiveGraph() 8 | fmt = ('json-ld' if source.endswith('.jsonld') else 9 | guess_format(source)) 10 | graph.parse(source, format=fmt, context=context) 11 | with open(query_file) as fp: 12 | query_text = fp.read().decode('utf-8') 13 | result = graph.query(query_text) 14 | for row in result: 15 | print('\t'.join(t.n3() if t else 'UNDEF' for t in row).encode('utf-8')) 16 | 17 | 18 | if __name__ == '__main__': 19 | from sys import argv 20 | args = argv[1:] 21 | source = args.pop(0) 22 | query_file = args.pop(0) 23 | context = 'build/vocab/context.jsonld' 24 | run_query(source, query_file, context) 25 | -------------------------------------------------------------------------------- /source/datasets/i18n.ttl: -------------------------------------------------------------------------------- 1 | prefix xsd: 2 | prefix : 3 | base 4 | 5 | # TODO: include these in idkbse.ttl when ready for QA! 6 | 7 | a :Dataset ; 8 | :uriSpace "https://id.kb.se/i18n/script/" ; 9 | :created "2022-10-14T16:26:16Z"^^xsd:dateTime ; 10 | :sourceData [ :uri "source/i18n/scripts.ttl" ] ; 11 | :derivedFrom . 12 | 13 | a :Dataset ; 14 | :uriSpace "https://id.kb.se/i18n/rule/" ; 15 | :sourceData [ :uri "source/i18n/rules.ttl" ] ; 16 | :created "2022-10-14T16:26:16Z"^^xsd:dateTime . 17 | 18 | a :Dataset ; 19 | :uriSpace "https://id.kb.se/i18n/lang/" ; 20 | :sourceData [ :uri "source/i18n/tlangs.ttl" ] ; 21 | :created "2022-10-24T13:32:22Z"^^xsd:dateTime . 22 | -------------------------------------------------------------------------------- /source/swepub/vocab.ttl: -------------------------------------------------------------------------------- 1 | prefix rdfs: 2 | prefix swepub: 3 | prefix : 4 | 5 | swepub:PublicationType a :EnumerationClass ; 6 | rdfs:subClassOf :GenreForm ; 7 | :category :pending . 8 | 9 | swepub:OutputType a :EnumerationClass ; 10 | rdfs:subClassOf :GenreForm ; 11 | :category :pending . 12 | 13 | swepub:ContentType a :EnumerationClass ; 14 | rdfs:subClassOf :GenreForm ; 15 | :category :pending . 16 | 17 | swepub:HostType a :EnumerationClass ; 18 | rdfs:subClassOf :GenreForm ; 19 | :category :pending . 20 | 21 | swepub:PublicationStatus a :EnumerationClass ; 22 | rdfs:label "Publication status"@en, "Publiceringsstatus"@sv ; 23 | rdfs:comment "Anmärkningar rörande verkets status"@sv; 24 | rdfs:subClassOf :Note ; #TODO Status?; 25 | :category :pending . 26 | -------------------------------------------------------------------------------- /source/datasets/signe.ttl: -------------------------------------------------------------------------------- 1 | prefix xsd: 2 | prefix : 3 | base 4 | 5 | a :Dataset ; 6 | :created "2022-02-19T09:06:00Z"^^xsd:dateTime ; 7 | :source ; 8 | :license . 9 | 10 | a :Dataset ; 11 | :uriSpace "https://libris.kb.se/dataset/signe/bib/" ; 12 | :created "2022-04-07T13:40:10Z"^^xsd:dateTime ; 13 | :sourceData [ :uri "../signe2librisxl/build/bibs.jsonld.lines" ] ; 14 | :isPartOf . 15 | 16 | a :Dataset ; 17 | :uriSpace "https://libris.kb.se/dataset/signe/edition/" ; 18 | :created "2022-04-19T10:00:00Z"^^xsd:dateTime ; 19 | :sourceData [ :uri "../signe2librisxl/build/editions.jsonld.lines" ] ; 20 | :dependsOn ; 21 | :isPartOf . 22 | -------------------------------------------------------------------------------- /source/construct-countries.rq: -------------------------------------------------------------------------------- 1 | prefix : 2 | prefix madsrdf: 3 | prefix xsd: 4 | prefix rdfs: 5 | prefix skos: 6 | prefix dc: 7 | 8 | construct { 9 | ?s ?p ?o ; 10 | skos:exactMatch ?loc ; 11 | skos:prefLabel ?prefLabel . 12 | 13 | } where { 14 | graph { 15 | { 16 | { 17 | ?s ?p ?o . 18 | } union { 19 | ?s skos:notation ?notation . 20 | graph { 21 | ?loc madsrdf:authoritativeLabel|skos:prefLabel ?prefLabel . 22 | filter strends(str(?loc), concat('/', ?notation)) 23 | } 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /source/construct-rda-terms.rq: -------------------------------------------------------------------------------- 1 | prefix madsrdf: 2 | prefix rdfs: 3 | prefix owl: 4 | prefix skos: 5 | 6 | construct { 7 | 8 | ?s ?p ?o ; 9 | rdfs:label ?lcLabel ; 10 | skos:prefLabel ?rdapreflabel ; 11 | skos:definition ?rdadefinition . 12 | 13 | } where { 14 | { 15 | graph { 16 | ?s ?p ?o . 17 | } 18 | } union { 19 | ?s skos:exactMatch ?lc . 20 | filter(strstarts(str(?lc), 'http://id.loc.gov/vocabulary/')) 21 | ?lc madsrdf:authoritativeLabel|skos:prefLabel ?lcLabel . 22 | } union { 23 | ?s skos:exactMatch ?rda . 24 | filter(strstarts(str(?rda), 'http://rdaregistry.info/termList/')) 25 | ?rda skos:prefLabel ?rdapreflabel ; 26 | skos:definition ?rdadefinition . 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /scripts/marc/README.md: -------------------------------------------------------------------------------- 1 | 2 | ## Generate the marcmap ## 3 | 4 | (Ask a co-worker for the config file sources.) 5 | 6 | 1. Get Swedish legacy config files and put them in a dir: 7 | 8 | $ CONFIG_SV=... 9 | 10 | 2. Get English legacy config files and put them in a dir: 11 | 12 | $ CONFIG_EN=... 13 | 14 | 3. Patch these files by hand (see parse_legacy_config.py for FIXME notes describing how). 15 | 16 | 4. Define (relative to this file): 17 | 18 | $ MARCMAP=../whelk-core/src/main/resources/marcmap.json 19 | 20 | 5. Run: 21 | 22 | $ python parse_legacy_config.py $CONFIG_EN/TagTable/Marc21 en $CONFIG_SV/TagTable/Marc21 sv > $MARCMAP 23 | 24 | 6. Download a FRBR CSV mapping: 25 | 26 | $ FRBR_CSV=... 27 | $ curl http://www.loc.gov/marc/marc-functional-analysis/source/FRBR_Web_Copy.txt -o $FRBR_CSV 28 | 29 | 7. Add frbr hints as entity annotations in the marcmap by running: 30 | 31 | $ python frbrize_marcmap.py $FRBR_CSV $MARCMAP > tmpout && mv tmpout $MARCMAP 32 | 33 | -------------------------------------------------------------------------------- /sys/context/target/loc-w3c-sdo.jsonld: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | {"bf2": "http://id.loc.gov/ontologies/bibframe/"}, 4 | {"bflc": "http://id.loc.gov/ontologies/bflc/"}, 5 | {"madsrdf": "http://www.loc.gov/mads/rdf/v1#"}, 6 | {"skos": "http://www.w3.org/2004/02/skos/core#"}, 7 | {"dc": "http://purl.org/dc/terms/"}, 8 | {"dctype": "http://purl.org/dc/dcmitype/"}, 9 | {"prov": "http://www.w3.org/ns/prov#"}, 10 | {"sdo": "http://schema.org/"}, 11 | {"bibo": "http://purl.org/ontology/bibo/"}, 12 | {"foaf": "http://xmlns.com/foaf/0.1/"}, 13 | {"void": "http://rdfs.org/ns/void#"}, 14 | {"owl": "http://www.w3.org/2002/07/owl#"}, 15 | {"rdfs": "http://www.w3.org/2000/01/rdf-schema#"}, 16 | {"rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#"}, 17 | {"xsd": "http://www.w3.org/2001/XMLSchema#"}, 18 | {"edtf": "http://id.loc.gov/datatypes/edtf/"}, 19 | {"ldp": "http://www.w3.org/ns/ldp#"} 20 | ], 21 | "created": "2021-10-18T14:18:25.440Z" 22 | } 23 | -------------------------------------------------------------------------------- /source/datasets/bibdb.ttl: -------------------------------------------------------------------------------- 1 | prefix xsd: 2 | prefix : 3 | base 4 | 5 | # IMPORTANT: these are currently self-described (the dataset description is 6 | # part of the dataset itself). If ever deleted and dataset items are remade 7 | # into "record-free" items, reloading the dataset will fail unless it is 8 | # forced, and if so it needs the descriptions below to compute the same 9 | # xl-id:s!) 10 | 11 | a :Dataset ; 12 | :created "2019-03-14T15:00:00.000Z"^^xsd:dateTime ; 13 | :dataSource ; 14 | :license . 15 | 16 | a :Dataset ; 17 | :created "2019-03-14T15:31:17.000Z"^^xsd:dateTime ; 18 | :uriSpace "https://libris.kb.se/library/" ; 19 | :isPartOf . 20 | 21 | a :Dataset ; 22 | :created "2019-03-14T19:32:20.000Z"^^xsd:dateTime ; 23 | :uriSpace "https://libris.kb.se/library/" ; 24 | :isPartOf . 25 | -------------------------------------------------------------------------------- /scripts/get-proxy-domains-ranges.rq: -------------------------------------------------------------------------------- 1 | prefix rdf: 2 | prefix rdfs: 3 | prefix owl: 4 | prefix : 5 | 6 | construct { 7 | 8 | ?property rdfs:domain ?domain . 9 | ?property rdfs:range ?range . 10 | 11 | } where { 12 | 13 | bind(str(:) as ?strvocab) 14 | 15 | ?property 16 | rdfs:subPropertyOf|owl:equivalentProperty ?baseproperty . 17 | { 18 | ?baseproperty rdfs:domain ?basedomain . 19 | ?domain (rdfs:subClassOf|owl:equivalentClass)* ?basedomain . 20 | } union { 21 | ?baseproperty rdfs:range ?baserange . 22 | ?range (rdfs:subClassOf|owl:equivalentClass)* ?baserange . 23 | } 24 | 25 | # ... rdfs:isDefinedBy ?vocab . 26 | filter(strstarts(str(?property), ?strvocab)) 27 | 28 | filter(!bound(?domain) || 29 | strstarts(str(?domain), ?strvocab)) 30 | 31 | filter(!bound(?range) || 32 | strstarts(str(?range), ?strvocab)) 33 | 34 | } 35 | -------------------------------------------------------------------------------- /datasets.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | 4 | from lxltools.datacompiler import Compiler 5 | import syscore 6 | import common 7 | import docs 8 | 9 | SCRIPT_DIR = os.path.dirname(__file__) or '.' 10 | BASE = "https://id.kb.se/" 11 | 12 | compiler = Compiler(base_dir=SCRIPT_DIR, 13 | dataset_id=BASE + 'dataset/definitions', 14 | created='2013-10-17T14:07:48.000Z', 15 | tool_id=BASE + 'generator/definitions', 16 | context='sys/context/base.jsonld', 17 | record_thing_link='mainEntity', 18 | system_base_iri='', 19 | union='definitions.jsonld.lines') 20 | 21 | if __name__ == '__main__': 22 | compiler.main() 23 | syscore.compiler.main() 24 | common.compiler.main() 25 | docs.compiler.main() 26 | 27 | out_dir = compiler.outdir 28 | with (out_dir / compiler.union).open('ab') as defs_f: 29 | for mod in [syscore, common, docs]: 30 | with (out_dir / mod.compiler.union).open('rb') as f: 31 | shutil.copyfileobj(f, defs_f) 32 | -------------------------------------------------------------------------------- /lxltools/timeutil.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime, timezone 2 | 3 | 4 | def nowstamp(): 5 | return datetime.now().timestamp() 6 | 7 | 8 | def w3c_dtz_to_ms(ztime: str): 9 | assert ztime.endswith('Z') 10 | try: # fromisoformat is new in Python 3.7 11 | return int(datetime.fromisoformat(ztime.replace('Z', '+00:00')) 12 | .timestamp() * 1000) 13 | except AttributeError: # fallback can be removed when we rely on Py 3.7+ 14 | ztime = ztime[:-1] # drop 'Z' 15 | if '.' not in ztime: 16 | ztime += '.000' # add millisecs to comply with format 17 | ztime += '+0000' # strptime-compliant UTC timezone format 18 | return int(datetime.strptime(ztime, '%Y-%m-%dT%H:%M:%S.%f%z') 19 | .timestamp() * 1000) 20 | 21 | 22 | def to_w3c_dtz(ms: float): 23 | dt = datetime.fromtimestamp(ms / 1000, tz=timezone.utc) 24 | return dt.isoformat(timespec='milliseconds').replace('+00:00', 'Z') 25 | 26 | 27 | def to_http_date(s: float): 28 | return datetime.utcfromtimestamp(s).strftime('%a, %d %b %Y %H:%M:%S GMT') 29 | -------------------------------------------------------------------------------- /source/construct-cc-license-data.rq: -------------------------------------------------------------------------------- 1 | PREFIX cc: 2 | PREFIX dct: 3 | PREFIX frbr: 4 | PREFIX owl: 5 | PREFIX xhv: 6 | 7 | CONSTRUCT { 8 | ?secure a cc:License ; 9 | owl:sameAs ?license ; 10 | ?p ?o ; 11 | dct:identifier ?identifier ; 12 | frbr:translation ?translation . 13 | } WHERE { 14 | GRAPH ?g { 15 | ?license a cc:License . 16 | OPTIONAL { ?license dct:identifier ?id } 17 | BIND(REPLACE(STR(?id), "^\\s*\\(|\\)\\s*$", "") AS ?identifier) 18 | } 19 | VALUES (?p) { 20 | (dct:creator) (dct:title) (cc:permits) (cc:requires) (cc:prohibits) (xhv:license) 21 | } 22 | ?license ?p ?o . 23 | OPTIONAL { 24 | ?license frbr:translation ?translation . 25 | FILTER(?translation = ?g) 26 | } 27 | BIND(IF(!BOUND(?translation) && ?g != ?license, ?g, ?nothing) AS ?same) 28 | BIND(IF(STRSTARTS(STR(?license), "http://"), 29 | IRI(CONCAT("https://", STRAFTER((STR(?license)), "http://"))), 30 | ?license) AS ?secure) 31 | } 32 | -------------------------------------------------------------------------------- /source/vocab/external-labels.ttl: -------------------------------------------------------------------------------- 1 | prefix rdfs: 2 | prefix owl: 3 | prefix schema: 4 | prefix ptg: 5 | 6 | rdfs:subClassOf rdfs:label "Har basklass"@sv, "Sub class of"@en ; 7 | owl:inverseOf [ rdfs:label "Basklass för"@sv, "Base class of"@en ] . 8 | 9 | rdfs:subPropertyOf rdfs:label "Har basegenskap"@sv, "Sub property of"@en ; 10 | owl:inverseOf [ rdfs:label "Basegenskap för"@sv, "Base property of"@en ] . 11 | 12 | owl:inverseOf rdfs:label "Invers av"@sv, "Inverse of"@en . 13 | 14 | rdfs:isDefinedBy rdfs:label "Definieras av"@sv, "Is defined by"@en . 15 | 16 | ptg:abstract rdfs:label "Abstrakt"@sv, "Abstract"@en . 17 | 18 | owl:equivalentClass rdfs:label "Motsvarar"@sv, "Equivalent class"@en . 19 | 20 | rdfs:domain rdfs:label "Förekommer på"@sv, "Domain"@en . 21 | 22 | schema:domainIncludes rdfs:label "Kan förekomma på"@sv, "Domain includes"@en . 23 | 24 | rdfs:range rdfs:label "Pekar på"@sv, "Range"@en . 25 | 26 | schema:rangeIncludes rdfs:label "Kan peka på"@sv, "Range includes"@en . 27 | 28 | owl:equivalentProperty rdfs:label "Motsvarar"@sv, "Equivalent property"@en . 29 | -------------------------------------------------------------------------------- /examples/mappings/libris-uri-scheme.ttl: -------------------------------------------------------------------------------- 1 | @prefix coin: . 2 | @prefix foaf: . 3 | @prefix bf: . 4 | @base . 5 | 6 | a coin:URISpace; 7 | coin:base "http://libris.kb.se"; 8 | coin:apply coin:ToLowerCase; 9 | coin:spaceReplacement "-"; 10 | coin:template [ 11 | coin:forType foaf:Document; 12 | coin:uriTemplate "/bib/{controlNumber}" 13 | ], [ 14 | coin:forType bf:Instance; 15 | coin:uriTemplate "/resource/bib/{recordControlNumber}" 16 | ], [ 17 | coin:forType bf:Work; 18 | coin:relFromBase bf:instanceOf; 19 | coin:uriTemplate "{+base}#work"; 20 | ] . 21 | 22 | # /bib/ 23 | # /auth/ 24 | # /resource/bib/ 25 | # /resource/auth/ 26 | # /resource/library/{sigel} # unused 27 | # /work/1 28 | 29 | @prefix xsd: . 30 | @prefix dct: . 31 | @prefix void: . 32 | @prefix skos: . 33 | 34 | a void:Dataset; 35 | coin:slug "person"^^xsd:anyURI; 36 | dct:created "2013-02-11T11:01:00Z"^^xsd:dateTime . 37 | 38 | -------------------------------------------------------------------------------- /scripts/load-defs-whelk.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | WHELK=$1 4 | FILTER=$2 5 | DOBUILD=$3 6 | BUILDBASE="build" 7 | 8 | put() { 9 | if [[ $3 == *"$FILTER"* ]]; then 10 | echo "PUT '$1' to <$3> as $2" 11 | curl -XPUT -H "Content-Type:$2" --data-binary @$1 $3?data 12 | fi 13 | } 14 | 15 | # Generate datasets 16 | if [[ $DOBUILD != "--nobuild" && $FILTER == "" ]]; then 17 | echo "Compile definitions..." 18 | python datasets.py -c cache/ -o $BUILDBASE/ 19 | echo "Done." 20 | fi 21 | 22 | # Load JSON-LD contexts 23 | libcontext=$BUILDBASE/lib-context.jsonld 24 | put $libcontext application/ld+json ${WHELK}/sys/context/lib.jsonld 25 | for ctx in owl skos; do 26 | put sys/context/${ctx}.jsonld application/ld+json ${WHELK}/sys/context/${ctx}.jsonld 27 | done 28 | 29 | # Load standalone documents 30 | for doc in terms schemes; do 31 | put $BUILDBASE/${doc}.jsonld application/ld+json ${WHELK}/def/$doc 32 | done 33 | 34 | # Load datasets 35 | for dataset in languages countries nationalities relators enum/{content,carrier,record}; do 36 | for file in $BUILDBASE/$dataset/*.jsonld; do 37 | slug=$(basename -s .jsonld $file) 38 | put $file application/ld+json ${WHELK}/def/${dataset}/$slug 39 | done 40 | done 41 | -------------------------------------------------------------------------------- /source/cc-licenses-header.txt: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # IMPORTANT: generated data (see ../Makefile)! 3 | # 4 | # Custom selection of license metadata from Creative Commons 5 | # (). 6 | # 7 | # According to the metadata, the licenses themselves are licensed under 8 | # . Since this URI designates the 9 | # *web page*, presumably this metadata is also published under that license. 10 | # 11 | # However, this is contradicted by the statements in their corresponding "legal 12 | # code" documents (e.g. at 13 | # ), which reads: 14 | # 15 | # > The text of the Creative Commons public licenses is dedicated to the public 16 | # > domain under the CC0 Public Domain Dedication. 17 | # 18 | # We have contacted Creative Commons to get a clarification of this. According 19 | # to them: 20 | # 21 | # > The legal text of the CC Licenses is dedicated to the public domain with 22 | # > CC0. Therefore the meta-data tags are also available under those terms. 23 | # 24 | # This is very accommodating, and facilitates any use and re-use of this 25 | # metadata. We leave this notice in place to be clear. 26 | ############################################################################### 27 | -------------------------------------------------------------------------------- /source/datasets/external.ttl: -------------------------------------------------------------------------------- 1 | prefix xsd: 2 | prefix : 3 | 4 | base 5 | 6 | a :Dataset ; 7 | :prefLabel "Dataset med QLIT-termer"@sv, "Dataset of QLIT terms"@en ; 8 | :uriSpace "https://queerlit.dh.gu.se/qlit/" ; 9 | :uriRegexPattern "https://queerlit\\.dh\\.gu\\.se/qlit/v1.*" ; 10 | :created "2022-05-19T08:12:00Z"^^xsd:dateTime ; 11 | :sourceData ; 12 | :datasetClass [ :broadMatch :Concept ; :closeMatch :Topic ] . 13 | 14 | a :Dataset ; 15 | :created "2022-10-13T13:25:01Z"^^xsd:dateTime ; 16 | :uriSpace "https://creativecommons.org/" ; 17 | :uriRegexPattern "https://creativecommons\\.org/.*" ; 18 | :sourceData [ :uri "source/cc-licenses.ttl" ; :derivedFrom ] ; 19 | :license . 20 | 21 | a :Dataset ; 22 | :created "2024-12-04T12:38:31Z"^^xsd:dateTime ; 23 | :uriSpace "https://begrepp.uka.se/SSIF/" ; 24 | :sourceData [ :uri "source/ssif-2025-skos.ttl" ; 25 | :derivedFrom ] ; 26 | :datasetClass [ :broadMatch :Concept ; :closeMatch :Classification ] . 27 | -------------------------------------------------------------------------------- /source/kbv-enums.ttl: -------------------------------------------------------------------------------- 1 | @prefix rdfs: . 2 | @prefix owl: . 3 | @prefix sdo: . 4 | @prefix skos: . 5 | @prefix : . 6 | @base . 7 | 8 | 9 | # Instances of ItemAvailability 10 | 11 | a sdo:ItemAvailability ; 12 | rdfs:label "Beställd" ; 13 | skos:prefLabel "Requested"@en, 14 | "Beställd"@sv . 15 | 16 | a sdo:ItemAvailability ; 17 | rdfs:label "Ej fjärrlån" ; 18 | skos:prefLabel "Not for ILL"@en, 19 | "Ej fjärrlån"@sv . 20 | 21 | a sdo:ItemAvailability ; 22 | rdfs:label "Ej hemlån" ; 23 | skos:prefLabel "Not for loan"@en, 24 | "Ej hemlån"@sv . 25 | 26 | a sdo:ItemAvailability ; 27 | rdfs:label "Levererad" ; 28 | skos:prefLabel "Delivered"@en, 29 | "Levererad"@sv . 30 | 31 | a sdo:ItemAvailability ; 32 | rdfs:label "Utlånas ej" ; 33 | skos:prefLabel "Not for check out"@en, 34 | "Utlånas ej"@sv . 35 | 36 | # Instances of DescriptionConventions 37 | 38 | a :DescriptionConventions; 39 | rdfs:label "RDA" ; 40 | skos:prefLabel "RDA"@en, "RDA"@sv ; 41 | skos:notation "rda" ; 42 | skos:exactMatch . -------------------------------------------------------------------------------- /scripts/marc/describe_marcmap.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | def describe_marcmap(marcmap): 4 | for tag, field in sorted(marcmap['bib'].items()): 5 | if tag == 'fixprops': 6 | continue 7 | print tag,_id_or_label(field) 8 | for fixmap in field.get('fixmaps', ()): 9 | print " ", fixmap.get('label_en', "").replace('&', '') 10 | for col in fixmap['columns']: 11 | print " {0} ({1}+{2})".format(*[col.get(key) for key in 12 | ('propRef', 'offset', 'length')]) 13 | if 'subfield' in field: 14 | # TODO: ind is a dict, *value* has _id_or_label 15 | #inds = ", ".join(filter(None, (_id_or_label(field[ind]) 16 | # for ind in ['ind1', 'ind2'] if ind in field))) 17 | inds = ", ".join(filter(None, (" ".join(field[ind].keys()) 18 | for ind in ['ind1', 'ind2'] if ind in field))) 19 | if inds: 20 | print " ", inds 21 | for code, subfield in field['subfield'].items(): 22 | print " ", code, subfield['id'] 23 | print 24 | 25 | def _id_or_label(data): 26 | return data.get('id') or data.get('label_en') 27 | 28 | 29 | if __name__ == '__main__': 30 | from sys import argv, exit 31 | import os 32 | if len(argv) < 2: 33 | print "Usage: {0} MARCMAP".format(os.path.basename(argv[0])) 34 | exit() 35 | fpath = argv[1] 36 | with open(fpath) as f: 37 | describe_marcmap(json.load(f)) 38 | 39 | -------------------------------------------------------------------------------- /scripts/misc/jsontr.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import re 3 | from collections import OrderedDict 4 | import json 5 | 6 | 7 | def camelize(data, source, dest=None): 8 | dest = dest or source 9 | for o in data.values(): 10 | if source not in o: continue 11 | v = o[source] 12 | o[dest] = v[0].lower() + re.sub(r"\W", "", v.title()[1:]) 13 | return data 14 | 15 | def sort_keys(o): 16 | out = OrderedDict() 17 | for key in sorted(o.keys()): 18 | out[key] = o[key] 19 | return out 20 | 21 | def to_list(o, keykey='key'): 22 | l = [] 23 | for k, v in o.items(): 24 | if isinstance(v, dict) and keykey not in v: 25 | v2 = OrderedDict() 26 | v2[keykey] = k 27 | v2.update(v) 28 | l.append(v2) 29 | else: 30 | l.append(v) 31 | return l 32 | 33 | def to_dict(data, keykey, keep=None): 34 | return OrderedDict( 35 | (v[keykey] if keep == 'keep' else v.pop(keykey), v) 36 | for v in data) 37 | 38 | def objectify(data, key): 39 | for k, v in data.items(): 40 | data[k] = {key: v} 41 | return data 42 | 43 | if __name__ == '__main__': 44 | import sys 45 | 46 | tr = vars()[sys.argv[1]] 47 | 48 | data = json.load(sys.stdin, object_pairs_hook=OrderedDict) 49 | data = tr(data, *sys.argv[2:]) 50 | 51 | print json.dumps(data, 52 | indent=2, 53 | ensure_ascii=False, 54 | separators=(',', ': ') 55 | ).encode('utf-8') 56 | -------------------------------------------------------------------------------- /source/vocab/update.rq: -------------------------------------------------------------------------------- 1 | prefix rdfs: 2 | prefix : 3 | 4 | insert { 5 | ?term rdfs:isDefinedBy : 6 | } where { 7 | ?term ?p ?o 8 | filter ((?term != :) && strstarts(str(?term), str(:))) 9 | }; 10 | 11 | # Remove uninteresting domain/range if there are specific ones. 12 | delete { 13 | ?s ?p rdfs:Resource 14 | } where { 15 | ?s ?p ?o 16 | filter(?o != rdfs:Resource && strstarts(str(?o), str(:))) 17 | filter(?p in (rdfs:subClassOf, rdfs:domain, rdfs:range)) 18 | }; 19 | 20 | # Remap domain/range if there are specific suggestions. 21 | delete { 22 | ?s ?domainOrRange rdfs:Resource 23 | # TODO: this is formally correct, but "mutes" the includes in the cataloguing tool... 24 | #} insert { 25 | # ?s ?domainOrRange :Resource 26 | } where { 27 | ?s ?includesRelation ?o 28 | filter(?o != rdfs:Resource && strstarts(str(?o), str(:))) 29 | 30 | values (?domainOrRange ?includesRelation) { 31 | (rdfs:domain sdo:domainIncludes) 32 | (rdfs:range sdo:rangeIncludes) 33 | } 34 | }; 35 | 36 | # remove redundant base classes 37 | delete { 38 | ?c rdfs:subClassOf ?a . 39 | } where { 40 | ?c rdfs:subClassOf / rdfs:subClassOf+ ?a . 41 | }; 42 | 43 | # remove disputed work sublasses 44 | delete { 45 | ?notawork rdfs:subClassOf :Work . 46 | } where { 47 | values (?notawork) { 48 | (:Manuscript) 49 | (:Collection) 50 | (:Integrating) 51 | (:Monograph) 52 | (:Serial) 53 | (:Series) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /source/bibliographies.jsonld: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "@vocab": "http://libris.kb.se/def/terms#", 4 | "bibliographyByNotation": {"@id": "@graph", "@container": "@index"}, 5 | "label": {"@language": "sv"} 6 | }, 7 | "bibliographyByNotation": { 8 | "BULB": { 9 | "notation": "BULB", 10 | "label": "BULB - Barn- och ungdomslitteraturbibliografin" 11 | }, 12 | "NB": { 13 | "notation": "NB", 14 | "label": "Nationalbibliografin - Böcker, Periodica, Kartor" 15 | }, 16 | "SEE": { 17 | "notation": "SEE", 18 | "label": "Seelig (bokdistributör)" 19 | }, 20 | "SLB": { 21 | "notation": "SLB", 22 | "label": "Svensk litteraturvetenskaplig bibliografi" 23 | }, 24 | "KVIN": { 25 | "notation": "KVIN", 26 | "label": "KVINNSAM" 27 | }, 28 | "SHB": { 29 | "notation": "SHB", 30 | "label": "Svensk historisk bibliografi" 31 | }, 32 | "SKvB": { 33 | "notation": "SKvB", 34 | "label": "Svensk konstvetenskaplig bibliografi" 35 | }, 36 | "SOT": { 37 | "notation": "SOT", 38 | "label": "Svenskt offentligt tryck -1833" 39 | }, 40 | "SMHB": { 41 | "notation": "SMHB", 42 | "label": "Svensk musikhistorisk bibliografi" 43 | }, 44 | "DALA": { 45 | "notation": "DALA", 46 | "label": "Dalabibliografin" 47 | }, 48 | "SUEC": { 49 | "notation": "SUEC", 50 | "label": "Suecana extranea" 51 | }, 52 | "SAH": { 53 | "notation": "SAH", 54 | "label": "Suecia Antiqua et Hodierna" 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /source/construct-relators.rq: -------------------------------------------------------------------------------- 1 | prefix rdfs: 2 | prefix owl: 3 | prefix skos: 4 | prefix bf2: 5 | prefix madsrdf: 6 | prefix : 7 | 8 | construct { 9 | ?s ?p ?o ; 10 | skos:prefLabel ?enLabel, ?fiLabel, ?deLabel, ?frLabel . 11 | 12 | } where { 13 | graph { 14 | { 15 | ?s ?p ?o . 16 | } union { 17 | ?s skos:exactMatch ?lc . 18 | graph { 19 | ?lc madsrdf:authoritativeLabel|skos:prefLabel ?lcLabel . 20 | bind(strlang(?lcLabel, 'en') as ?enLabel) 21 | } 22 | } union { 23 | ?s skos:exactMatch ?mts . 24 | graph { 25 | ?mts skos:prefLabel ?fiLabel . 26 | filter(lang(?fiLabel) = 'fi') 27 | } 28 | } union { 29 | ?s skos:exactMatch ?dnb . 30 | graph { 31 | ?dnb rdfs:label ?deLabel . 32 | filter(lang(?deLabel) = 'de') 33 | } 34 | } union { 35 | ?s skos:exactMatch ?bnf . 36 | graph { 37 | ?bnf skos:prefLabel ?frLabel . 38 | filter(lang(?frLabel) = 'fr') 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /examples/mappings/bibframe-identifiers.ttl: -------------------------------------------------------------------------------- 1 | @prefix rdfs: . 2 | @prefix owl: . 3 | @prefix : . 4 | @prefix ext: . 5 | 6 | 7 | :isbn a owl:DatatypeProperty; 8 | owl:propertyChainAxiom ( 9 | [ a owl:ObjectProperty; 10 | rdfs:subPropertyOf :identifier; 11 | rdfs:range [ a owl:Restriction; 12 | owl:onProperty :identifierScheme; owl:hasValue "ISBN" ] ] 13 | :identifierValue ) . 14 | 15 | :invalidIsbn a owl:DatatypeProperty; 16 | owl:propertyChainAxiom ( 17 | [ a owl:ObjectProperty; 18 | rdfs:subPropertyOf :identifier; 19 | rdfs:range [ a owl:Restriction; 20 | owl:onProperty :identifierScheme; owl:hasValue "ISBN" ], 21 | [ a owl:Restriction; 22 | owl:onProperty :identifierStatus; owl:hasValue "invalid" ] ] 23 | :identifierValue ) . 24 | 25 | 26 | ext:agentLink a owl:ObjectProperty; 27 | owl:inverseOf rdf:subject; 28 | owl:range :AgentLink . 29 | 30 | ext:AgentLink a owl:Class; 31 | owl:subClassOf rdf:Statement, [ 32 | a owl:Restriction; owl:onProperty ext:relator; owl:hasValue :associatedAgent 33 | ] . 34 | 35 | ext:relator a owl:ObjectProperty; 36 | rdfs:subPropertyOf rdf:predicate; 37 | owl:domain ext:AgentLink . 38 | 39 | ext:agent a owl:ObjectProperty; 40 | rdfs:subPropertyOf rdf:object; 41 | owl:domain ext:AgentLink . 42 | 43 | -------------------------------------------------------------------------------- /docs.py: -------------------------------------------------------------------------------- 1 | import os 2 | import markdown 3 | from lxltools.datacompiler import Compiler 4 | 5 | BASE = "https://id.kb.se/" 6 | 7 | SCRIPT_DIR = os.path.dirname(__file__) or '.' 8 | 9 | compiler = Compiler(base_dir=SCRIPT_DIR, 10 | dataset_id=BASE + 'dataset/docs', 11 | created='2016-04-15T14:42:00.000Z', 12 | tool_id=BASE + 'generator/docsbuilder', 13 | context='sys/context/base.jsonld', 14 | record_thing_link='mainEntity', 15 | system_base_iri='', 16 | union='docs.jsonld.lines') 17 | 18 | 19 | @compiler.dataset 20 | def id_docs(): 21 | docs = [] 22 | sourcepath = compiler.path('source') 23 | for fpath in (sourcepath / 'doc').glob('**/*.mkd'): 24 | text = fpath.read_text('utf-8') 25 | html = markdown.markdown(text) 26 | doc_id = (str(fpath.relative_to(sourcepath)) 27 | .replace(os.sep, '/') 28 | .replace('.mkd', '')) 29 | doc_id, dot, lang = doc_id.partition('.') 30 | doc = { 31 | "@type": "Article", 32 | "@id": BASE + doc_id, 33 | "articleBody": html 34 | } 35 | h1end = html.find('') 36 | if h1end > -1: 37 | doc['title'] = html[len('

'):h1end] 38 | if lang: 39 | doc['language'] = {"langTag": lang}, 40 | docs.append(doc) 41 | 42 | return "/doc", "2016-04-15T14:43:38.072Z", { 43 | "@context": "../sys/context/base.jsonld", 44 | "@graph": docs 45 | } 46 | 47 | 48 | if __name__ == '__main__': 49 | compiler.main() 50 | -------------------------------------------------------------------------------- /source/construct-languages-iso639-1.rq: -------------------------------------------------------------------------------- 1 | prefix rdfs: 2 | prefix xsd: 3 | prefix skos: 4 | prefix madsrdf: 5 | prefix dc: 6 | prefix iso639_1: 7 | prefix kbv: 8 | prefix langtag: 9 | 10 | construct { 11 | ?s ?p ?o ; 12 | owl:sameAs ?bcp47alias ; 13 | skos:notation ?langCodeShort, ?langTag ; 14 | skos:closeMatch ?locVariant . 15 | } where { 16 | graph { 17 | ?s ?p ?o . 18 | optional { 19 | ?s skos:prefLabel ?prefLabel . 20 | graph { 21 | ?locVariant madsrdf:authoritativeLabel|skos:prefLabel ?prefLabel 22 | bind(substr(str(?locVariant), strlen(str(iso639_1:)) + 1) as ?shortcode) 23 | bind(strdt(?shortcode, kbv:ISO639-1) as ?langCodeShort) 24 | } 25 | } 26 | optional { 27 | ?s skos:notation ?iso639_2 . 28 | filter(datatype(?iso639_2) = kbv:ISO639-2) 29 | } 30 | optional { 31 | ?s skos:notation ?iso639_3 . 32 | filter(datatype(?iso639_3) = kbv:ISO639-3) 33 | } 34 | bind(str( 35 | coalesce(?langCodeShort, 36 | coalesce(?iso639_2, ?iso639_3)) 37 | ) as ?langTagStr) 38 | bind(strdt(?langTagStr, kbv:BCP47) as ?langTag) 39 | bind(IRI(concat(str(langtag:), ?langTagStr)) as ?bcp47alias) 40 | } 41 | } 42 | 43 | -------------------------------------------------------------------------------- /source/marc/base.ttl: -------------------------------------------------------------------------------- 1 | @prefix rdf: . 2 | @prefix rdfs: . 3 | @prefix xsd: . 4 | @prefix owl: . 5 | @prefix skos: . 6 | @prefix bf2: . 7 | @prefix schema: . 8 | @prefix kbv: . 9 | @prefix marc: . 10 | @prefix : . 11 | 12 | # Use these to define which MARC category a class belongs to. 13 | :auth a skos:Collection ; :code "auth" . 14 | :bib a skos:Collection ; :code "bib" . 15 | :hold a skos:Collection ; :code "hold" . 16 | 17 | # TODO: please write a rationale for these terms since they are not part of the data. 18 | 19 | :Field a owl:Class ; 20 | rdfs:subClassOf rdfs:Resource . 21 | 22 | :subField a rdf:Property ; 23 | rdfs:domain :Field . 24 | 25 | :data a owl:ObjectProperty; 26 | rdfs:range rdf:List . 27 | 28 | :parts a owl:ObjectProperty; 29 | rdfs:range rdf:List . 30 | 31 | :value a owl:DatatypeProperty ; 32 | rdfs:range xsd:string . 33 | 34 | :RecordType a owl:Class ; 35 | rdfs:subClassOf skos:Collection . 36 | 37 | :recordType a owl:ObjectProperty . 38 | 39 | :repeatable a owl:DatatypeProperty . 40 | 41 | :CollectionClass a owl:Class ; 42 | rdfs:subClassOf owl:Class, skos:Collection . 43 | 44 | :EnumeratedTerm a owl:Class ; 45 | rdfs:subClassOf schema:Enumeration, kbv:Concept . 46 | 47 | :EnumeratedClass a owl:Class ; 48 | rdfs:subClassOf :EnumeratedTerm, owl:Class . 49 | 50 | :MainEntry a owl:Class; rdfs:subClassOf bf2:Contribution . 51 | 52 | :AddedEntry a owl:Class; rdfs:subClassOf bf2:Contribution . 53 | -------------------------------------------------------------------------------- /scripts/analyze-enums.py: -------------------------------------------------------------------------------- 1 | import re 2 | from collections import OrderedDict 3 | import json 4 | 5 | enums = json.load(open('source/enums.jsonld')) 6 | 7 | collection_sets = set() 8 | coll_values = {} 9 | 10 | for item in enums.get('@graph') or enums['enumDefs'].values(): 11 | colls = item.get('inCollection') 12 | if colls: 13 | for c in colls: 14 | coll_values.setdefault(c['@id'], []).append(item['@id']) 15 | collection_sets.add(tuple(sorted(c['@id'] for c in colls))) 16 | 17 | value_sets = {} 18 | 19 | for cset in collection_sets: 20 | for c in cset: 21 | name = c 22 | members = set(coll_values[c]) 23 | value_sets.setdefault(tuple(sorted(members)), set()).add(name) 24 | 25 | def common_key(terms): 26 | prev = set() 27 | keys = [] 28 | for term in terms: 29 | key = term.rsplit('/', 1)[-1] 30 | keys.append(key) 31 | parts = set(re.findall(r'[A-Z][^A-Z]*', term)) 32 | candidates = prev & parts if prev else parts 33 | if not candidates: 34 | candidates = parts | prev 35 | prev = candidates 36 | return "Or".join(keys) if len(candidates) > 1 else next(iter(candidates)) 37 | 38 | equivs = OrderedDict() 39 | for values, equiv_colls in value_sets.items(): 40 | if len(equiv_colls) > 1: 41 | equivs[common_key(equiv_colls)] =\ 42 | [{'values': values}] + \ 43 | list(equiv_colls) 44 | 45 | def dump(data): 46 | print(json.dumps(data, indent=2, sort_keys=True, separators=(',', ': '))) 47 | 48 | print "# Equivalent collections:" 49 | dump(equivs) 50 | 51 | print "# Map:" 52 | cmap = {} 53 | for key, paths in equivs.items(): 54 | cmap[key] = [path.rsplit('/', 1)[-1] for path in paths if isinstance(path, unicode)] 55 | dump(cmap) 56 | -------------------------------------------------------------------------------- /source/construct-languages-iso639-2.rq: -------------------------------------------------------------------------------- 1 | prefix rdfs: 2 | prefix xsd: 3 | prefix skos: 4 | prefix madsrdf: 5 | prefix dc: 6 | prefix iso639_2: 7 | prefix kbv: 8 | 9 | construct { 10 | ?s ?p ?o ; 11 | skos:prefLabel ?prefLabel ; 12 | skos:altLabel ?altLabel ; 13 | skos:exactMatch ?locLang ; 14 | } where { 15 | graph { 16 | { 17 | ?s ?p ?o . 18 | } union { 19 | ?s skos:notation ?locCode . 20 | filter( 21 | datatype(?locCode) = kbv:ISO639-2-T || 22 | datatype(?locCode) = xsd:string 23 | ) 24 | bind(iri(concat(str(iso639_2:), str(?locCode))) as ?locLang) 25 | graph { 26 | { 27 | filter(!contains(?prefLabel, "|")) 28 | ?locLang madsrdf:authoritativeLabel|skos:prefLabel ?prefLabel 29 | } union { 30 | filter(contains(?prefLabels, "|")) 31 | ?locLang madsrdf:authoritativeLabel|skos:prefLabel ?prefLabels 32 | bind(replace(?prefLabels, " *\\|.*$", "") as ?prefLabel) 33 | bind(replace(?prefLabels, "^[^|]+\\| *", "") as ?altLabels) 34 | values ?n { 1 2 3 4 5 6 7 } 35 | bind(concat("^([^|]+\\|){", str(?n) ,"} *") as ?skipN) 36 | bind(replace(replace(?altLabels, ?skipN, ""), " *\\|.*$", "") as ?altLabel) 37 | } 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /source/vocab/check-bases.rq: -------------------------------------------------------------------------------- 1 | prefix rdfs: 2 | prefix owl: 3 | prefix dct: 4 | prefix sdo: 5 | prefix : 6 | 7 | construct { 8 | 9 | ?check a :Warning; :message ?msg; :implicated (?base ?term) . 10 | 11 | } where { 12 | 13 | { 14 | ?term (rdfs:subClassOf|owl:equivalentClass) ?base . 15 | filter not exists { 16 | { ?base a rdfs:Class } union { ?base a owl:Class } union { ?base a rdfs:Datatype } 17 | } 18 | bind("Unknown base class {} for term {}"@en as ?msg) 19 | 20 | } union { 21 | ?term (rdfs:subPropertyOf|owl:equivalentProperty) ?base . 22 | filter not exists { 23 | { ?base a rdf:Property } 24 | union { ?base a owl:DatatypeProperty } 25 | union { ?base a owl:ObjectProperty } 26 | union { ?base a owl:SymmetricProperty } 27 | union { ?base a owl:TransitiveProperty } 28 | } 29 | bind("Unknown base property {} for term {}"@en as ?msg) 30 | 31 | } union { 32 | ?term (rdfs:domain|sdo:domainIncludes) ?base . 33 | filter not exists { 34 | { ?base a rdfs:Class } union { ?base a owl:Class } 35 | } 36 | bind("Unknown domain {} for term {}"@en as ?msg) 37 | 38 | } union { 39 | ?term (rdfs:range|sdo:rangeIncludes) ?base . 40 | filter not exists { 41 | { ?base a rdfs:Class } union { ?base a owl:Class } 42 | } 43 | bind("Unknown range {} for term {}"@en as ?msg) 44 | } 45 | 46 | bind(bnode(str(?base)) as ?check) 47 | 48 | filter(isIRI(?term) && isIRI(?base) 49 | && strStarts(str(?base), replace(str(?term), '[^#/:]+$', ''))) 50 | 51 | } 52 | -------------------------------------------------------------------------------- /source/swepub/types.ttl: -------------------------------------------------------------------------------- 1 | prefix : 2 | prefix skos: 3 | prefix swepub: 4 | prefix sppubl: 5 | prefix spout: 6 | 7 | swepub:ArtisticWork a :GenreForm ; 8 | skos:exactMatch sppubl:kfu, spout:artistic-work . 9 | 10 | swepub:Book a :GenreForm ; 11 | skos:exactMatch sppubl:bok, spout:publication\/book . 12 | 13 | swepub:BookChapter a :GenreForm ; 14 | skos:exactMatch sppubl:kap, spout:publication\/book-chapter . 15 | 16 | swepub:ConferencePaper a :GenreForm ; 17 | skos:closeMatch sppubl:kon\/ref, spout:conference\/paper . 18 | 19 | swepub:DoctoralThesis a :GenreForm ; 20 | skos:exactMatch sppubl:dok, spout:publication\/doctoral-thesis . 21 | 22 | swepub:EditorialCollection a :GenreForm ; 23 | skos:exactMatch sppubl:sam, spout:publication\/edited-book . 24 | 25 | swepub:EditorialProceedings a :GenreForm ; 26 | skos:exactMatch sppubl:pro, spout:conference\/proceeding . 27 | 28 | swepub:JournalArticle a :GenreForm ; 29 | skos:closeMatch sppubl:art\/ref, spout:publication\/journal-article . 30 | 31 | swepub:LicentiateThesis a :GenreForm ; 32 | skos:exactMatch sppubl:lic, spout:publication\/licentiate-thesis . 33 | 34 | swepub:OtherPublication a :GenreForm ; 35 | skos:exactMatch sppubl:ovr, spout:publication . 36 | 37 | swepub:Patent a :GenreForm ; 38 | skos:exactMatch sppubl:pat, spout:intellectual-property\/patent . 39 | 40 | swepub:Report a :GenreForm ; 41 | skos:exactMatch sppubl:rap, spout:publication\/report . 42 | 43 | swepub:ResearchReview a :GenreForm ; 44 | skos:exactMatch sppubl:for, spout:publication\/review-article . 45 | 46 | swepub:Review a :GenreForm ; 47 | skos:exactMatch sppubl:rec, spout:publication\/book-review . 48 | 49 | -------------------------------------------------------------------------------- /source/generators.ttl: -------------------------------------------------------------------------------- 1 | @prefix rdfs: . 2 | @prefix prov: . 3 | @prefix bf2: . 4 | 5 | a bf2:GenerationProcess ; 6 | rdfs:label "The Definitions Dataset Generator of Libris XL"@en . 7 | 8 | a bf2:GenerationProcess ; 9 | rdfs:label "The MarcFrame Conversion Process of Libris XL"@en . 10 | 11 | a bf2:GenerationProcess ; 12 | rdfs:label "The Global Changes Process of Libris XL"@en, "Libris XL:s globala ändringar"@sv . 13 | 14 | a prov:SoftwareAgent ; 15 | rdfs:label "Swepub Autoclassifier"@en, "Swepubs autoklassificering"@sv . 16 | 17 | a bf2:GenerationProcess ; 18 | rdfs:label "The APIX subsystem of Libris XL"@en, "APIX"@sv . 19 | 20 | a bf2:GenerationProcess ; 21 | rdfs:label "The batch import subsystem of Libris XL"@en . 22 | 23 | a bf2:GenerationProcess ; 24 | rdfs:label "The pre-2018 implementation of Libris"@en . 25 | 26 | a bf2:GenerationProcess ; 27 | rdfs:label "The WhelkCopier subsystem of Libris XL, used to copy data between Libris XL instances"@en . 28 | 29 | a bf2:GenerationProcess ; 30 | rdfs:label "The REST API of Libris XL"@en, "Libris XL:s REST-API"@sv . 31 | 32 | a bf2:GenerationProcess ; 33 | rdfs:label "The Libris XL Cataloguing Tool"@en, "Libris katalogisering"@sv . 34 | 35 | a bf2:GenerationProcess ; 36 | rdfs:label "The Work Merger Tool"@en, "Automatisk Verkssammanslagning"@sv . 37 | -------------------------------------------------------------------------------- /source/doc/issues/record-thing.en.mkd: -------------------------------------------------------------------------------- 1 | # Record/Thing 2 | 3 | * Some items are just documents; we still put their administrative metadata in a "record", but note that they are embedded? 4 | 5 | * for all other things, sparse records administrate the things (even vocab and skos terms) 6 | 7 | * Some items are just things (persons, websites, ...), but *really*, their descriptions are (partial) records (e.g. dbpedia quotes), even if empty (though at least @id + dc:modified...) 8 | 9 | * Mostly(?), if a thing is given, it's the most interesting entity (possible conflict: AgentTerm and Agent...; from the library management POV, not for discovery...) 10 | 11 | SOURCE: 12 | 13 | <1> [ 14 | {id: 1, a Record, mainEntity 1#term}, 15 | {id: 1#it, a Person} 16 | {id: 1#term, a Term; focus 1#it} 17 | ] 18 | 19 | INDEX: 20 | 21 | Term 22 | focus 23 | Person 24 | meta 25 | Record 26 | 27 | SOURCE: 28 | 29 | <2> [ 30 | {id: 2, a Record, mainEntity 2#it}, 31 | {id: 2#it, a Person} 32 | ] 33 | 34 | INDEX: 35 | 36 | Person 37 | meta 38 | Record 39 | 40 | SOURCE: 41 | 42 | <2> [ 43 | {id: 3, a Document} 44 | ] 45 | 46 | INDEX: 47 | 48 | Document 49 | meta 50 | Record (known-admin-parts-of) 51 | 52 | We *no longer* use: 53 | 54 | GRAPH { 55 | 56 | 57 | :mainEntity . 58 | 59 | 60 | :meta ; # description 61 | :focus . # concretization 62 | 63 | 64 | :meta ; 65 | :hasAuthority . # abstraction 66 | 67 | } 68 | 69 | (See also [Concept/Thing Design Issue](/doc/issues/concept-thing).) 70 | -------------------------------------------------------------------------------- /source/movementnotation.ttl: -------------------------------------------------------------------------------- 1 | @prefix rdfs: . 2 | @prefix owl: . 3 | @prefix sdo: . 4 | @prefix skos: . 5 | @prefix : . 6 | #@base . TODO: Define in datasets. movnotation or notemove. 7 | 8 | @prefix rdafnv: . 9 | 10 | 11 | # MOVEMENT NOTATION linked to rdaregistry.com (No id.loc.gov counterpart 2021-05-27) 12 | 13 | a :MovementNotation ; 14 | skos:prefLabel "Stepanovnotation"@sv ; 15 | skos:notation "1001" ; 16 | skos:exactMatch rdafnv:1001 . 17 | 18 | a :MovementNotation ; 19 | skos:prefLabel "Labanotation"@sv ; 20 | skos:notation "1002" ; 21 | skos:exactMatch rdafnv:1002 . 22 | 23 | a :MovementNotation ; 24 | skos:prefLabel "Spelnotation"@sv ; 25 | skos:notation "1004" ; 26 | skos:exactMatch rdafnv:1003 . 27 | 28 | a :MovementNotation ; 29 | skos:prefLabel "Eshkol-Wachmannotation"@sv ; 30 | skos:notation "1005" ; 31 | skos:exactMatch rdafnv:1005 . 32 | 33 | a :MovementNotation ; 34 | skos:notation "1006" ; 35 | skos:exactMatch rdafnv:1006 . 36 | 37 | a :MovementNotation ; 38 | skos:prefLabel "Beneshnotation"@sv ; 39 | skos:notation "1007" ; 40 | skos:exactMatch rdafnv:1007 . 41 | 42 | a :MovementNotation ; 43 | skos:prefLabel "Feuilletnotation"@sv ; 44 | skos:notation "1008" ; 45 | skos:exactMatch rdafnv:1008 . 46 | 47 | a :MovementNotation ; 48 | skos:notation "1009" ; 49 | skos:exactMatch rdafnv:1009 . 50 | 51 | a :MovementNotation ; 52 | skos:notation "1010" ; 53 | skos:exactMatch rdafnv:1010 . -------------------------------------------------------------------------------- /source/tactilenotation.ttl: -------------------------------------------------------------------------------- 1 | @prefix rdfs: . 2 | @prefix owl: . 3 | @prefix sdo: . 4 | @prefix skos: . 5 | @prefix : . 6 | @base . 7 | 8 | @prefix rdaftn: . 9 | @prefix marctac: . 10 | 11 | # TACTILE NOTATION linked to id.loc.gov and rdaregistry.com 12 | 13 | a :TactileNotation ; 14 | skos:prefLabel "Punktskrift"@sv ; 15 | skos:notation "1001" ; 16 | :code "brail" ; 17 | skos:exactMatch rdaftn:1001, marctac:brail . 18 | 19 | a :TactileNotation ; 20 | skos:prefLabel "Punktskrift för databehandling"@sv ; 21 | skos:notation "1002" ; 22 | :code "comp" ; 23 | skos:exactMatch rdaftn:1002, marctac:comp . 24 | 25 | a :TactileNotation ; 26 | skos:prefLabel "Matematisk och naturvetenskaplig punktskrift"@sv ; 27 | skos:notation "1003" ; 28 | :code "math" ; 29 | skos:exactMatch rdaftn:1003, marctac:math . 30 | 31 | a :TactileNotation ; 32 | skos:prefLabel "Moonskrift"@sv; 33 | skos:notation "1004" ; 34 | :code "moon" ; 35 | skos:exactMatch rdaftn:1004, marctac:moon . 36 | 37 | a :TactileNotation ; 38 | skos:prefLabel "Punktskrift för musik"@sv ; 39 | skos:notation "1005" ; 40 | :code "music" ; 41 | skos:exactMatch rdaftn:1005, marctac:music . 42 | 43 | a :TactileNotation ; 44 | skos:prefLabel "Taktil musiknotation"@sv ; 45 | skos:notation "1006" ; 46 | :code "tactm" ; 47 | skos:exactMatch rdaftn:1006, marctac:tactm . 48 | 49 | a :TactileNotation ; 50 | skos:prefLabel "Taktil grafik"@sv ; 51 | skos:notation "1007" ; 52 | :code "graph" ; 53 | skos:exactMatch rdaftn:1006, marctac:graph . -------------------------------------------------------------------------------- /lxltools/ldutil.py: -------------------------------------------------------------------------------- 1 | from rdflib import Graph 2 | from rdflib.plugins.serializers.jsonld import from_rdf 3 | from rdflib.plugins.parsers.jsonld import to_rdf 4 | 5 | 6 | def to_jsonld(source: Graph, context_uri: str, contextobj) -> dict: 7 | data = from_rdf(source, context_data=contextobj) 8 | data['@context'] = context_uri 9 | _embed_singly_referenced_bnodes(data) 10 | _expand_ids(data['@graph'], contextobj['@context']) 11 | return data 12 | 13 | 14 | def _expand_ids(obj, pfx_map): 15 | """ 16 | Ensure @id values are in expanded form (i.e. full URIs). 17 | """ 18 | if isinstance(obj, list): 19 | for item in obj: 20 | _expand_ids(item, pfx_map) 21 | elif isinstance(obj, dict): 22 | node_id = obj.get('@id') 23 | if node_id: 24 | pfx, colon, leaf = node_id.partition(':') 25 | ns = pfx_map.get(pfx) 26 | if ns: 27 | obj['@id'] = node_id.replace(pfx + ':', ns, 1) 28 | for value in obj.values(): 29 | _expand_ids(value, pfx_map) 30 | 31 | 32 | def _embed_singly_referenced_bnodes(data): 33 | graph_index = {item['@id']: item for item in data.pop('@graph')} 34 | bnode_refs = {} 35 | 36 | def collect_refs(node): 37 | for values in node.values(): 38 | if not isinstance(values, list): 39 | values = [values] 40 | for value in values: 41 | if isinstance(value, dict): 42 | if value.get('@id', '').startswith('_:'): 43 | bnode_refs.setdefault(value['@id'], []).append(value) 44 | collect_refs(value) 45 | 46 | for node in graph_index.values(): 47 | collect_refs(node) 48 | 49 | for refid, refs in bnode_refs.items(): 50 | if len(refs) == 1: 51 | refs[0].update(graph_index.pop(refid)) 52 | refs[0].pop('@id') 53 | 54 | data['@graph'] = sorted(graph_index.values(), key=lambda node: node['@id']) 55 | -------------------------------------------------------------------------------- /scripts/extract-marcframe-terms.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals, print_function, division 2 | from collections import Counter 3 | import json 4 | 5 | 6 | def get_keywords(marcframe, ignore_speced=False): 7 | keywords = Counter() 8 | speced = set() 9 | for key, part in marcframe.items(): 10 | if not isinstance(part, dict): 11 | continue 12 | for field in part.values(): 13 | if not field: 14 | continue 15 | is_speced = any(kw in field for kw in ['_specSource', '_spec']) 16 | if not isinstance(field, dict): 17 | #print "Skipping:", field 18 | continue 19 | for kw, obj in field.items(): 20 | if '$' in kw or kw in {'i1', 'i2'} or kw[0].isupper(): 21 | if obj: 22 | if not isinstance(obj, dict): 23 | continue 24 | for subkw, subobj in obj.items(): 25 | if subkw.startswith('['): 26 | keywords.update(subobj.keys()) 27 | if is_speced: 28 | speced |= set(subobj) 29 | else: 30 | keywords[subkw] += 1 31 | if is_speced: 32 | speced.add(kw) 33 | elif not kw.startswith('['): 34 | keywords[kw] += 1 35 | if is_speced: 36 | speced.add(kw) 37 | if ignore_speced: 38 | for k in speced: 39 | del keywords[k] 40 | return keywords 41 | 42 | 43 | if __name__ == '__main__': 44 | import sys 45 | args = sys.argv[1:] 46 | source = args.pop(0) 47 | 48 | with open(source) as fp: 49 | marcframe = json.load(fp) 50 | 51 | keywords = get_keywords(marcframe) 52 | for kw, i in keywords.most_common(): 53 | if 'NOTE:' in kw.upper() or 'TODO' in kw.upper(): 54 | continue 55 | print(kw, i) 56 | -------------------------------------------------------------------------------- /source/changecategories.ttl: -------------------------------------------------------------------------------- 1 | prefix skos: 2 | prefix : 3 | 4 | base 5 | 6 | a :ChangeCategory ; 7 | skos:prefLabel "Primary contribution"@en, "Primär medverkan"@sv ; 8 | skos:altLabel "Change of primary contribution"@en, "Ändring av primär medverkan"@sv . 9 | 10 | a :ChangeCategory ; 11 | skos:prefLabel "Main title"@en, "Huvudtitel"@sv ; 12 | skos:altLabel "Change of main title"@en, "Ändring av huvudtitel"@sv . 13 | 14 | a :ChangeCategory ; 15 | skos:prefLabel "Key title"@en, "Nyckeltitel"@sv ; 16 | skos:altLabel "Change of key title"@en, "Ändring av nyckeltitel"@sv . 17 | 18 | a :ChangeCategory ; 19 | skos:prefLabel "Agent as subject"@en, "Agent som ämne"@sv ; 20 | skos:altLabel "Change of agent as subject"@en, "Ändring av agent som ämne"@sv . 21 | 22 | a :ChangeCategory ; 23 | skos:prefLabel "Intended audience"@en, "Målgrupp"@sv ; 24 | skos:altLabel "Change of intended audience"@en, "Ändring av målgrupp"@sv . 25 | 26 | a :ChangeCategory ; 27 | skos:prefLabel "DDC classification"@en, "DDK-klassifikation"@sv ; 28 | skos:altLabel "Change of DDC classification"@en, "Ändring av DDK-klassifikation"@sv . 29 | 30 | a :ChangeCategory ; 31 | skos:prefLabel "SAB classification"@en, "SAB-klassifikation"@sv ; 32 | skos:altLabel "Change of SAB classification"@en, "Ändring av SAB-klassifikation"@sv . 33 | 34 | a :ChangeCategory ; 35 | skos:prefLabel "Serial relationships"@en, "Serierelation"@sv ; 36 | skos:altLabel "Change of serial relationships"@en, "Ändring av serierelation"@sv . 37 | 38 | a :ChangeCategory ; 39 | skos:prefLabel "Discontinued serial resource"@en, "Avslutad seriell resurs"@sv . 40 | 41 | a :ChangeCategory ; 42 | skos:prefLabel "Change in agent (too many affected instances for individual notifications)"@en, "Ändring av agent (för många påverkade instanser för att kunna meddelas var för sig)"@sv . 43 | -------------------------------------------------------------------------------- /source/musicnotation.ttl: -------------------------------------------------------------------------------- 1 | @prefix rdfs: . 2 | @prefix owl: . 3 | @prefix sdo: . 4 | @prefix skos: . 5 | @prefix : . 6 | @base . 7 | 8 | @prefix rdafmn: . 9 | @prefix marcmus: . 10 | 11 | 12 | # MUSICAL NOTATION linked to id.loc.gov and rdaregistry.com 13 | 14 | a :MusicNotation ; 15 | skos:prefLabel "Grafisk notation"@sv ; 16 | skos:notation "1001" ; 17 | :code "graph" ; 18 | skos:exactMatch rdafmn:1001, marcmus:graph . 19 | 20 | a :MusicNotation ; 21 | skos:prefLabel "Bokstavsnotation"@sv ; 22 | skos:notation "1002" ; 23 | :code "letter" ; 24 | skos:exactMatch rdafmn:1002, marcmus:letter . 25 | 26 | a :MusicNotation ; 27 | skos:prefLabel "Mensuralnotation"@sv ; 28 | skos:notation "1003" ; 29 | :code "mensu" ; 30 | skos:exactMatch rdafmn:1003, marcmus:mensu . 31 | 32 | a :MusicNotation ; 33 | skos:prefLabel "Siffernotation"@sv ; 34 | skos:notation "1004" ; 35 | :code "numb" ; 36 | skos:exactMatch rdafmn:1004, marcmus:numb . 37 | 38 | #NOTE: 1005: plainsong, 1006: solmization (solmisation) deprecated. 39 | 40 | a :MusicNotation ; 41 | skos:prefLabel "Traditionell västerländsk notskrift"@sv; 42 | skos:notation "1007" ; 43 | :code "staff" ; 44 | skos:exactMatch rdafmn:1007, marcmus:staff . 45 | 46 | a :MusicNotation ; 47 | skos:prefLabel "Tabulatur"@sv ; 48 | skos:notation "1008" ; 49 | :code "tabla" ; 50 | skos:exactMatch rdafmn:1008, marcmus:tabla . 51 | 52 | a :MusicNotation ; 53 | skos:prefLabel "Tonic sol-fa"@sv ; 54 | skos:notation "1009" ; 55 | :code "tonic" ; 56 | skos:exactMatch rdafmn:1009, marcmus:tonic . 57 | 58 | a :MusicNotation ; 59 | skos:prefLabel "Neumer"@sv ; 60 | skos:notation "1010" ; 61 | :code "neuma" ; 62 | skos:exactMatch rdafmn:1010, marcmus:neuma . 63 | 64 | a :MusicNotation ; 65 | skos:notation "1011" ; 66 | #NOTE: NO marc counterpart. 67 | skos:exactMatch rdafmn:1011 . -------------------------------------------------------------------------------- /lxltools/lxlslug.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from __future__ import unicode_literals, print_function 3 | 4 | from zlib import crc32 5 | import string 6 | import time 7 | import random 8 | 9 | 10 | lower_consonants_numbers = string.digits + "".join( 11 | c for c in string.ascii_lowercase if c not in "aoueiy") 12 | 13 | def tobase(alphabet, i): 14 | v = '' 15 | size = len(alphabet) 16 | n = i 17 | while True: 18 | n, rest = divmod(n, size) 19 | v = alphabet[rest] + v 20 | if not n: 21 | return v 22 | 23 | def caesarize(alphabet, s): 24 | size = len(alphabet) 25 | last = s[-1] 26 | rotation = alphabet.index(last) 27 | def rotate(c): 28 | pos = alphabet.index(c) + rotation 29 | return pos - size if pos >= size else pos 30 | return "".join(alphabet[rotate(c)] for c in s[:-1]) + last 31 | 32 | def checksum(data): 33 | return crc32(data.encode('utf-8')) & 0xffffffff 34 | 35 | def librisencode(a, b): 36 | alphabet = lower_consonants_numbers 37 | timepart = "".join(reversed(caesarize(alphabet, tobase(alphabet, a)))) 38 | codepart = tobase(alphabet, b) 39 | codelen = len(codepart) 40 | if codelen < 7: 41 | codepart = ("0" * (7 - codelen)) + codepart 42 | return timepart + codepart 43 | 44 | 45 | if __name__ == '__main__': 46 | import sys 47 | import os.path as P 48 | 49 | args = sys.argv[:] 50 | cmd = P.basename(args.pop(0)) 51 | 52 | if len(args) < 2: 53 | print("Usage: %s TIMESTAMP IDENTIFIER" % (cmd), file=sys.stderr) 54 | exit(1) 55 | 56 | timestamp = args.pop(0) 57 | identifiers = args 58 | 59 | try: 60 | timestamp = int(timestamp) 61 | except ValueError: 62 | timestamp, dot, frag = timestamp.partition('.') 63 | timestamp = (time.mktime( 64 | time.strptime(timestamp, "%Y-%m-%dT%H:%M:%S")) * 1000) 65 | if frag: 66 | assert len(frag) < 4 67 | timestamp += + int(frag) 68 | 69 | def faux_offset(s): 70 | return sum(ord(c) * ((i+1) ** 2) for i, c in enumerate(s)) 71 | 72 | for identifier in identifiers: 73 | offset = faux_offset(identifier) 74 | check = checksum(identifier) 75 | slug = librisencode(int(timestamp + offset), check) 76 | print("<{}> = <{}> # {}, {}".format(slug, identifier, offset, check)) 77 | -------------------------------------------------------------------------------- /bibdb_datasets.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | from lxltools.datacompiler import Compiler 3 | import os 4 | 5 | 6 | SCRIPT_DIR = os.path.dirname(__file__) or '.' 7 | BASE = 'https://libris.kb.se/' 8 | 9 | 10 | compiler = Compiler(base_dir=SCRIPT_DIR, 11 | dataset_id=BASE + 'dataset/bibdb', 12 | context='sys/context/base.jsonld', 13 | record_thing_link='mainEntity', 14 | system_base_iri="", 15 | union='libraries.jsonld.lines', 16 | created="2019-03-14T15:00:00.000Z") 17 | 18 | 19 | @compiler.dataset 20 | def libraries(): 21 | graph = _construct_bibdb_data('sigel=*&holdings=True&org_type=library') 22 | return "/library", "2019-03-14T15:31:17.000Z", graph 23 | 24 | 25 | @compiler.dataset 26 | def bibliographies(): 27 | graph = _construct_bibdb_data('sigel=*&org_type=bibliography') 28 | return "/library", "2019-03-14T19:32:20.000Z", graph 29 | 30 | 31 | def _construct_bibdb_data(query): 32 | libraries = _fetch_libraries(f'https://bibdb.libris.kb.se/api?{query}') 33 | bidb_context = 'https://bibdb.libris.kb.se/libdb/static/meta/context.jsonld' 34 | return compiler.construct(sources=[ 35 | { 36 | "dataset": BASE + "dataset/libraries", 37 | "data": libraries, 38 | "context": [ 39 | compiler.load_json(compiler.cache_url(bidb_context)), 40 | { 41 | "@base": "http://bibdb.libris.kb.se/", 42 | # TODO: these are dropped in the source context; fix that and drop this 43 | "date_created": "http://libris.kb.se/def/lib#date_created", 44 | "date_modified": "http://libris.kb.se/def/lib#date_modified", 45 | } 46 | ] 47 | } 48 | ], 49 | query="source/construct-libraries.rq") 50 | 51 | 52 | def _fetch_libraries(start_url): 53 | url = start_url 54 | result = [] 55 | 56 | start = 0 57 | batch = 200 58 | while True: 59 | data = compiler.load_json(compiler.cache_url(url)) 60 | libraries = data['libraries'] 61 | if libraries: 62 | result += libraries 63 | start += batch 64 | url = f'{start_url}&start={start}' 65 | else: 66 | break 67 | 68 | return result 69 | 70 | 71 | if __name__ == '__main__': 72 | compiler.main() 73 | -------------------------------------------------------------------------------- /source/vocab/libris-search-experimental.ttl: -------------------------------------------------------------------------------- 1 | @prefix rdfs: . 2 | @prefix owl: . 3 | @prefix sdo: . 4 | @prefix skos: . 5 | @prefix : . 6 | 7 | @prefix rdf: . 8 | @prefix xsd: . 9 | 10 | :LibrisQueryCode a rdfs:Datatype . 11 | 12 | :author a owl:ObjectProperty ; 13 | rdfs:label "författare"@sv, "author"@en ; 14 | :category :shorthand, :pending ; 15 | owl:equivalentProperty ; 16 | rdfs:subPropertyOf :contributor ; 17 | rdfs:range :Agent ; 18 | skos:notation "FÖRF"^^:LibrisQueryCode ; 19 | owl:propertyChainAxiom ( 20 | [ rdfs:subPropertyOf :contribution ; rdfs:range [ rdfs:subClassOf [ a owl:Restriction ; 21 | owl:onProperty :role ; 22 | owl:hasValue ] ] ] 23 | :agent 24 | ) . 25 | 26 | :isbn rdfs:domain :Instance . # See ./details.ttl for full definition of :isbn 27 | 28 | :yearPublished rdfs:label "utgivningsår"@sv, "year of publication"@en ; # See ./details.ttl for full definition of :yearPublished 29 | rdfs:domain :Instance ; 30 | skos:notation "ÅR"^^:LibrisQueryCode . 31 | 32 | :language skos:notation "SPRÅK"^^:LibrisQueryCode . # See ./relations.ttl for full definition of :language 33 | 34 | :controlNumber skos:notation "ONR"^^:LibrisQueryCode . # See ./platform.ttl for full definition of :controlNumber 35 | 36 | :itemHeldBy a owl:ObjectProperty ; 37 | rdfs:label "Bibliotek"@sv, "Library"@en ; 38 | :category :shorthand, :pending ; 39 | rdfs:domain :Instance ; 40 | sdo:rangeIncludes :Library ; 41 | owl:propertyChainAxiom ( :hasItem :heldBy ) . 42 | 43 | :instanceOfType a owl:ObjectProperty ; 44 | :category :shorthand, :pending ; 45 | rdfs:domain :Instance ; 46 | owl:propertyChainAxiom ( :instanceOf rdf:type ) . 47 | 48 | :hasInstanceType a owl:ObjectProperty ; 49 | rdfs:label "format"@sv, "format"@en ; 50 | skos:notation "FORMAT"^^:LibrisQueryCode ; 51 | :category :shorthand, :pending ; 52 | rdfs:domain :Work ; 53 | owl:propertyChainAxiom ( :hasInstance rdf:type ) . 54 | 55 | :originalLanguage a owl:ObjectProperty ; 56 | rdfs:label "originalspråk"@sv, "original language"@en ; 57 | :category :shorthand, :pending ; 58 | rdfs:domain :Work ; 59 | rdfs:range :Language ; 60 | owl:propertyChainAxiom ( :translationOf :language ) . 61 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | source/cc-licenses.ttl: source/construct-cc-license-data.rq 2 | cat source/cc-licenses-header.txt > $@ 3 | (echo https://creativecommons.org/publicdomain/mark/1.0/ && echo https://creativecommons.org/publicdomain/mark/1.0/deed.sv && curl -sL https://creativecommons.org/about/cclicenses/ | sed -nE 's!.*> $@ 4 | 5 | source/sab.ttl: scripts/extract_sab_data_from_docx.py cache/esab-2015_1.docx 6 | python3 $^ | trld -ijsonld -ottl > $@ 7 | # TODO 1: enhance with DDC-mappings: scripts/create_sab_skos_data.py + 8 | # ../librisxl/whelk-core/src/main/java/se/kb/libris/export/dewey/dewey_sab.txt 9 | # TODO 2: In XL, add precomposed usages (extract from usage in records)? See: 10 | # ../librisxl/marc_export/src/main/resources/se/kb/libris/export/sabrub.txt # precomposed 11 | 12 | ## SSIF 2011 (Obsolete) 13 | # 14 | #cache/ssif.xlsx: 15 | # curl https://www.uka.se/download/18.11258e6a184d17a7b2c2e5/1669982839699/Forskningsamnen-standard-2011.xlsx -o cache/ssif.xlsx 16 | # 17 | # See: . 18 | # * 9 = Tab 19 | # * 90 = UTF-8 20 | #cache/ssif.csv: cache/ssif.xlsx 21 | # libreoffice --headless --convert-to csv:"Text - txt - csv (StarCalc)":"9,ANSI,90" $^ --outdir cache/ 22 | # 23 | #source/ssif.jsonld: scripts/create_ssif_science_topic_data.py cache/ssif.csv 24 | # python3 $^ > $@ 25 | # 26 | #source/ssif.ttl: source/ssif.jsonld 27 | # trld $^ -o ttl > $@ 28 | 29 | ## SSIF 2025 30 | 31 | # - External source form (to be published at/via uka.se) 32 | source/ssif-2025-skos.ttl: cache/ssif-2025-skos.jsonld 33 | trld $^ -o ttl > $@ 34 | 35 | cache/ssif-2025-skos.jsonld: scripts/create_ssif_science_topic_data.py cache/ssif-2025.csv 36 | python3 $^ --skos > $@ 37 | 38 | # - Internal target form (to be fetched from source, mapped using TVM and cached in XL) 39 | source/ssif-2025-kbv.jsonld: scripts/create_ssif_science_topic_data.py cache/ssif-2025.csv 40 | python3 $^ > $@ 41 | 42 | # ...,2 = Sheet 2 - see 43 | cache/ssif-2025.csv: cache/Nyckel_SSIF2011_SSIF2025_digg.xlsx 44 | libreoffice --headless --convert-to csv:"Text - txt - csv (StarCalc)":"9,ANSI,90,,,true,true,false,false,,,2" cache/Nyckel_SSIF2011_SSIF2025_digg.xlsx --outdir cache/ 45 | # Fix incomplete change type 46 | sed -i '/^60411.*\tBytt benämning\t/ s/Bytt benämning/Ny kod, Bytt benämning/' "cache/Nyckel_SSIF2011_SSIF2025_digg-Nyckel SSIF2011-SSIF25.csv" 47 | cp "cache/Nyckel_SSIF2011_SSIF2025_digg-Nyckel SSIF2011-SSIF25.csv" $@ 48 | -------------------------------------------------------------------------------- /scripts/misc/mk-graph-data.py: -------------------------------------------------------------------------------- 1 | import json 2 | from rdflib import * 3 | from rdflib.util import guess_format 4 | 5 | 6 | VANN = Namespace("http://purl.org/vocab/vann/") 7 | 8 | 9 | def to_graph(paths): 10 | g = Graph() 11 | for fpath in paths: 12 | g.parse(fpath, format=guess_format(fpath)) 13 | return g 14 | 15 | def get_name(r, lang): 16 | for label in []:#r.objects(RDFS.label): 17 | name = unicode(label) 18 | if label.language == lang: 19 | break 20 | else: 21 | name = r.qname() 22 | return name 23 | 24 | def in_vocab(r, vocab): 25 | if not vocab.endswith(':'): 26 | r.graph.bind('', URIRef(vocab)) 27 | if isinstance(r.identifier, BNode): 28 | return False 29 | return ':' not in r.qname() or r.qname().startswith(vocab) 30 | 31 | 32 | def make_vocab_tree(g, lang, vocab): 33 | topclasses = [] 34 | for rclass in g.resource(OWL.Class).subjects(RDF.type): 35 | if any(pc for pc in rclass.objects(RDFS.subClassOf) if in_vocab(pc, vocab)): 36 | continue 37 | topclasses.append(tree_node(rclass, lang)) 38 | return { 39 | 'name': 'Thing', 40 | 'children': topclasses 41 | } 42 | 43 | def tree_node(rclass, lang): 44 | name = get_name(rclass, lang) 45 | children = [tree_node(sc, lang) for sc in rclass.subjects(RDFS.subClassOf)] 46 | node = {'name': name} 47 | if children: 48 | node['children'] = children 49 | return node 50 | 51 | 52 | def make_vocab_graph(g, lang, vocab): 53 | nodes = [] 54 | classes = set(g.resource(r) for r, o in g.subject_objects(RDF.type) 55 | if o in {RDFS.Class, OWL.Class}) 56 | for rclass in classes: 57 | if not in_vocab(rclass, vocab): 58 | continue 59 | name = get_name(rclass, lang) 60 | child_names = [get_name(sc, lang) for sc in rclass.subjects(RDFS.subClassOf)] 61 | node = {'name': name, 'children': child_names} 62 | node['termgroups'] = map(unicode, rclass.objects(VANN.termGroup)) 63 | nodes.append(node) 64 | 65 | return {'nodes': sorted(nodes, key=lambda node: node['name'])} 66 | 67 | 68 | if __name__ == '__main__': 69 | import sys 70 | args = sys.argv[1:] 71 | kind = args.pop(0) 72 | lang = 'sv' 73 | vocab = args.pop(0) 74 | g = to_graph(args) 75 | if kind == 'tree': 76 | data = make_vocab_tree(g, lang, vocab) 77 | else: 78 | data = make_vocab_graph(g, lang, vocab) 79 | print json.dumps(data, sort_keys=True, ensure_ascii=False, 80 | indent=2, separators=(',', ': ')).encode('utf-8') 81 | -------------------------------------------------------------------------------- /source/containers.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | 3 | a :EntityContainer ; 4 | :membershipResource ; 5 | :isMemberOfRelation :inScheme ; 6 | :memberClass :Topic, :Temporal, :Geographic, :ComplexSubject, :TopicSubdivision ; 7 | :slugProperty :prefLabel ; 8 | :administeredBy . 9 | 10 | a :EntityContainer ; 11 | :membershipResource ; 12 | :isMemberOfRelation :inScheme ; 13 | :memberClass :GenreForm ; 14 | :slugProperty :prefLabel ; 15 | :administeredBy . 16 | 17 | a :EntityContainer ; 18 | :membershipResource ; 19 | :isMemberOfRelation :inScheme ; 20 | :memberClass :Topic, :Temporal ; 21 | :slugProperty :prefLabel ; 22 | :administeredBy , 23 | . 24 | 25 | a :EntityContainer ; 26 | :membershipResource ; 27 | :isMemberOfRelation :inScheme ; 28 | :memberClass :GenreForm ; 29 | :slugProperty :prefLabel ; 30 | :administeredBy , 31 | . 32 | 33 | a :EntityContainer ; 34 | :membershipResource ; 35 | :isMemberOfRelation :inScheme ; 36 | :memberClass :GenreForm ; 37 | :slugProperty :prefLabel ; 38 | :administeredBy . 39 | 40 | a :EntityContainer ; 41 | :membershipResource ; 42 | :isMemberOfRelation :inScheme ; 43 | :memberClass :Classification ; 44 | :slugProperty :code ; 45 | :administeredBy . 46 | 47 | # other existing systems: 48 | 49 | a :EntityContainer ; 50 | :membershipResource ; 51 | :isMemberOfRelation :inScheme ; 52 | :memberClass :Topic, :Temporal, :Geographic, :ComplexSubject, :TopicSubdivision ; 53 | :slugProperty :prefLabel ; 54 | :administeredBy . 55 | 56 | a :EntityContainer ; 57 | :membershipResource ; 58 | :isMemberOfRelation :inScheme ; 59 | :memberClass :Topic, :Temporal, :Geographic, :ComplexSubject, :TopicSubdivision ; 60 | :slugProperty :prefLabel ; 61 | :administeredBy . 62 | -------------------------------------------------------------------------------- /sys/context/base.jsonld: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "skos": "http://www.w3.org/2004/02/skos/core#", 4 | "void": "http://rdfs.org/ns/void#", 5 | "foaf": "http://xmlns.com/foaf/0.1/", 6 | "dc": "http://purl.org/dc/terms/", 7 | "hydra": "http://www.w3.org/ns/hydra/core#", 8 | "@vocab": "https://id.kb.se/vocab/", 9 | "marc": "https://id.kb.se/marc/", 10 | "bibdb": "https://id.kb.se/ns/bibdb/", 11 | 12 | "@import": "./shared.jsonld", 13 | 14 | "value": "rdf:value", 15 | "sameAs": {"@id": "owl:sameAs", "@container": "@set"}, 16 | 17 | "Concept": "skos:Concept", 18 | "ConceptCollection": "skos:Collection", 19 | "ConceptScheme": "skos:ConceptScheme", 20 | 21 | "label": "rdfs:label", 22 | "comment": "rdfs:comment", 23 | "prefLabel": "skos:prefLabel", 24 | "altLabel": "skos:altLabel", 25 | "hiddenLabel": "skos:hiddenLabel", 26 | "code": "skos:notation", 27 | "note": "skos:note", 28 | "example": "skos:example", 29 | "definition": "skos:definition", 30 | "scopeNote": "skos:scopeNote", 31 | "changeNote": "skos:changeNote", 32 | "editorialNote": "skos:editorialNote", 33 | "historyNote": "skos:historyNote", 34 | "inDataset": "void:inDataset", 35 | 36 | "title": "dc:title", 37 | "alternative": "dc:alternative", 38 | "description": "dc:description", 39 | "license": "dc:license", 40 | 41 | "isPrimaryTopicOf": "foaf:isPrimaryTopicOf", 42 | "homepage": "foaf:homepage", 43 | "page": "foaf:page", 44 | 45 | "broadMatch": {"@id": "skos:broadMatch", "@container": "@set"}, 46 | "broader": {"@id": "skos:broader", "@container": "@set"}, 47 | "closeMatch": {"@id": "skos:closeMatch", "@container": "@set"}, 48 | "exactMatch": {"@id": "skos:exactMatch", "@container": "@set"}, 49 | "inScheme": {"@id": "skos:inScheme"}, 50 | "narrowMatch": {"@id": "skos:narrowMatch", "@container": "@set"}, 51 | "relatedMatch": {"@id": "skos:relatedMatch", "@container": "@set"}, 52 | "narrower": {"@id": "skos:narrower", "@container": "@set"}, 53 | "related": {"@id": "skos:related", "@container": "@set"}, 54 | "hasTopConcept": {"@id": "skos:hasTopConcept", "@container": "@set"}, 55 | 56 | "hasVersion": {"@id": "dc:hasVersion"}, 57 | "isVersionOf": {"@id": "dc:isVersionOf"}, 58 | "isReplacedBy": {"@id": "dc:isReplacedBy"}, 59 | "language": {"@id": "dc:language"}, 60 | 61 | "GenerationProcess": "http://id.loc.gov/ontologies/bibframe/GenerationProcess", 62 | "Country": "sdo:Country", 63 | "Language": "sdo:Language", 64 | "Role": "http://id.loc.gov/ontologies/bibframe/Role", 65 | "ItemAvailability": "sdo:ItemAvailability", 66 | 67 | "ContentType": "http://id.loc.gov/ontologies/bibframe/Content", 68 | "MediaType": "http://id.loc.gov/ontologies/bibframe/Media", 69 | "CarrierType": "http://id.loc.gov/ontologies/bibframe/Carrier", 70 | "IssuanceType": "http://id.loc.gov/ontologies/bibframe/Issuance" 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /source/policies.ttl: -------------------------------------------------------------------------------- 1 | prefix rdfs: 2 | prefix skos: 3 | prefix dct: 4 | prefix : 5 | base 6 | 7 | a :AccessPolicy ; 8 | skos:prefLabel "Fritt tillgänglig"@sv, "Freely available"@en . 9 | 10 | a :AccessPolicy ; 11 | skos:prefLabel "Öppen tillgång"@sv, "Open access"@en ; 12 | skos:altLabel "gratis"@en ; 13 | rdfs:comment "Användaren kommer åt resursen/fulltexten utan inloggning/betalning."@sv . 14 | 15 | a :AccessPolicy ; 16 | skos:prefLabel "Restriktioner för åtkomst"@sv, "Restricted access"@en ; 17 | skos:altLabel "restricted"@en ; 18 | rdfs:comment "Prenumeration eller inloggning behövs för åtkomst till resursen/fulltexten."@sv . 19 | 20 | a :UsePolicy ; 21 | skos:prefLabel "KB:s villkor för digitala samlingar"@sv, "KB Usage Policy for Digital Collections"@en ; 22 | dct:description """ 23 | De samlingar som Kungliga biblioteket tillhandahåller via Internet innehåller verk som är skyddade av upphovsrätt enligt upphovsrättslagen (SFS 1960:729). De innehåller också verk som inte är skyddade av upphovsrätt. 24 | 25 | För de verk i dessa samlingar som är skyddade av upphovsrätt har Kungl. biblioteket tecknat licenser med organisationer som företräder de som har upphovsrätten. Licenserna ger Kungl. biblioteket rätt att visa det upphovsrättsskyddade materialet på Internet. 26 | 27 | Verk som inte är skyddade av upphovsrätt får användas fritt. Verk som är skyddade av upphovsrätt har du inte rätt att sprida utan upphovsmannens godkännande. 28 | 29 | Kungl. biblioteket kan inte lämna något godkännande om vidare spridning av upphovsrättsligt skyddat material. Sådant tillstånd lämnas av upphovsmannen eller de som har upphovsrätten. Kungl. biblioteket kan inte hjälpa till med att utreda om verk är upphovsrättsligt skyddade eller inte. 30 | 31 | Det är du som användare som ansvarar för att ta reda på om materialet är upphovsrättsligt skyddat och att få godkännande om du vill sprida det vidare. 32 | """@sv ; 33 | :seeAlso ; 34 | :publisher . 35 | 36 | a :AccessPolicy ; 37 | skos:prefLabel "Filer kan krypteras vid nedladdning"@sv, "Files may be encrypted upon download"@en ; 38 | :seeAlso ; 39 | :publisher . 40 | 41 | a :AccessPolicy ; 42 | skos:prefLabel "Tillgänglig för personer med läsnedsättning enligt § 17 Upphovsrättslagen"@sv, "Available for persons with reading disabilities according to § 17 of the Copyright Act"@en; 43 | :seeAlso ; 44 | :publisher . -------------------------------------------------------------------------------- /source/i18n/rules.ttl: -------------------------------------------------------------------------------- 1 | prefix : 2 | base 3 | 4 | a :LanguageTransformRules ; 5 | :label "Lessing"@sv ; 6 | :description "Translitterering enligt Ferdinand Lessings schema"@sv ; 7 | :code "lessing" ; 8 | :seeAlso ; 9 | :inCollection . 10 | 11 | a :LanguageTransformRules ; 12 | :label "SKR 1980"@sv ; 13 | :description "Translitterering enligt Svenska katalogiseringsregler 1980 (SKR)"@sv ; 14 | :code "skr-1980" ; 15 | :seeAlso ; 16 | :inCollection . 17 | 18 | a :LanguageTransformRules ; 19 | :label "KR76"@sv ; 20 | :description "Transkribering enligt folkbibliotekens praxis (Kjellberg)"@sv ; 21 | :code "kr76" ; 22 | :seeAlso ; 23 | :inCollection . 24 | 25 | a :LanguageTransformRules ; 26 | :label "ISO/R 9:1968"@sv ; 27 | :description "Translitterering enligt ISO/R 9:1968"@sv ; 28 | :code "iso-1968" ; 29 | :seeAlso ; 30 | :seeAlso ; 31 | :inCollection . 32 | 33 | a :LanguageTransformRules ; 34 | :label "ISO 9:1995"@sv ; 35 | :description "Translitterering enligt ISO 9:1995"@sv ; 36 | :code "iso-1995" ; 37 | :seeAlso ; 38 | :seeAlso ; 39 | :inCollection . 40 | 41 | a :LanguageTransformRules ; 42 | :label "BTJ"@sv ; 43 | :description "Transkribering enligt BTJ:s praxis för folkbiblioteken"@sv ; 44 | :code "btj" ; 45 | :seeAlso ; 46 | :inCollection . 47 | 48 | a :LanguageTransformRules ; 49 | :label "YIVO"@sv ; 50 | :description "Romanisering enligt YIVO Institute for Jewish Research"@sv ; 51 | :code "yivo" ; 52 | :seeAlso ; 53 | :inCollection . 54 | 55 | a :LanguageTransformRules ; 56 | :label "ALA-LC"@sv ; 57 | :description "Romanisering enligt ALA-LC (American Library Association och Library of Congress)"@sv ; 58 | :code "alaloc" ; 59 | :seeAlso ; 60 | :inCollection . 61 | -------------------------------------------------------------------------------- /source/doc/about.sv.mkd: -------------------------------------------------------------------------------- 1 | # Om id.kb.se 2 | 3 | ## Inledning 4 | 5 | **id.kb.se** är en tjänst som tillgängliggör de grundstenar Kungliga biblioteket använder för att publicera strukturerade, [länkade data](https://sv.wikipedia.org/wiki/L%C3%A4nkad_data). Här finns gemensamma definitioner och begrepp som hjälper till att samordna beskrivningar av vårt material. Dessa utgår från och länkar till internationella, välkända motsvarigheter i möjligaste mån. 6 | 7 | Länkade data är en metod för att publicera strukturerade data på ett sätt som gör det möjligt för maskiner att skapa kopplingar mellan olika informationsobjekt och datakällor. På KB finns mycket data som kan länkas samman med annan data på Internet och på så sätt möjliggöra att datat berikas åt båda håll. 8 | 9 | ## Identifikatorer 10 | 11 | Varje begrepp, som t.ex. ett ämnesord, identifieras med hjälp av en HTTP-URI. URI:n består av en adress och en textsträng som tillsammans utgör begreppets unika identifikator. Exempel: `https://libris.kb.se/rp354vn9510f7x9`. 12 | 13 | Du som använder begreppen i egna system bör lagra de kompletta strängarna (`https://...`) i din databas. 14 | 15 | Vissa begrepp får även en mer "läsbar" identifikator baserat på den föredragna benämningen för begreppet. Exemplet ovan, som identifierar ämnesordet "Kommunikation", har fått den alternativa identifikatorn: `https://id.kb.se/term/sao/Kommunikation` Men du bör använda formen `https://libris.kb.se/rp354vn9510f7x9` när du lagrar den lokalt i ditt system. 16 | 17 | ## Metadataformat 18 | 19 | Under flikarna Basvokabulär och MARC-mappningar visas formatet utifrån olika perspektiv.  20 | Bakomliggande metadata presenteras för närvarande i 3 olika syntaxer: 21 | 22 | * [JSON-LD](http://json-ld.org/) (JavaScript Object Notation for Linked Data) 23 | * [RDF/XML](https://www.w3.org/TR/rdf-syntax-grammar/), ett format för att uttrycka RDF (Resource Description Framework) i XML. 24 | * [Turtle](http://www.w3.org/TR/turtle/) (Terse RDF Triple Language), ett format för att uttrycka RDF i en syntax som liknar SPARQL. 25 | 26 | Vår metadata uttrycks för närvarande med ett format baserat på [BIBFRAME 2.0](http://www.loc.gov/bibframe/docs/index.html), kompletterat med etablerade standarder, bl.a. 27 | [Dublin Core](http://purl.org/dc/terms/), 28 | [SKOS](http://www.w3.org/2004/02/skos/core#) och 29 | [MADS/RDF](http://www.loc.gov/mads/rdf/v1#). 30 | 31 | Dessa urskiljs i metadata med olika prefix som`bf`, `dc:`, `skos:`, och `madsrdf:`, med flera. De flesta vokabulären är beskrivna på ett sådant sätt som möjliggör att man ska kunna få ut data i flera olika etablerade standarder. 32 | 33 | En del information som är av mer administrativ karaktär och där vi ännu inte funnit motsvarande standardvokabulär har gett "lokala" prefix såsom `marc:` och `kbv:`. Termer som har prefixet `marc:` kommer inte att underhållas för persistens över tid medans kbv-termerna kan räknas till en mer stabil karaktär, även om dessa också kan innehålla kategorier för experimentella konstruktioner. För mer detaljer kring det och den datamodell vi använder, se artikeln [Data Model (på engelska)](https://github.com/libris/definitions/wiki/Data-Model). 34 | 35 | 36 | -------------------------------------------------------------------------------- /source/app/help.jsonld: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#", 4 | "rdfs": "http://www.w3.org/2000/01/rdf-schema#", 5 | "dc": "http://purl.org/dc/terms/", 6 | "skos": "http://www.w3.org/2004/02/skos/core#", 7 | "app": "http://kat.libris.kb.se/def/application#", 8 | "index": {"@container": "@index", "@id": "@graph"}, 9 | "label": {"@id": "rdfs:label", "@language": "sv"}, 10 | "comment": {"@id": "rdfs:comment", "@language": "sv"}, 11 | "example": {"@id": "skos:example"}, 12 | "descriptionHTML": {"@id": "dc:description", "@type": "rdf:HTML"} 13 | }, 14 | "index": { 15 | "app:restrictedURI": { 16 | "@id": "app:restrictedURI", 17 | "label": "URI för åtkomstbegränsade resurser", 18 | "descriptionHTML": "

Endast för fulltexter och liknande där åtkomsten är begränsad till bibliotekets användare, t.ex. via proxy eller IP-nummerfiltrering.

Klicka på ”Visa fler fält” om URI:n (webbadressen) behöver kompletteras med anmärkning etc.
Exempel
URI
http://ezproxy.its.uu.se/login?url=http://gateway.proquest.com/openurl?url_ver=Z39.88-2004&res_dat=xri:eurobo:&rft_dat=xri:eurobo:image:den-kbd-pil-130018150272-001
Publik anmärkning
Tillgänglig för användare inom Uppsala universitet

Observera att URI (webbadress) till fritt tillgängliga fulltexter ska anges i den bibliografiska posten (registreras tills vidare endast via Voyager)

" 19 | }, 20 | "app:offers": { 21 | "@id": "app:offers", 22 | "label": "Placering", 23 | "descriptionHTML": "

Bibliotekets sigel är obligatorisk och förifylld. Klicka på ”Spara bestånd” om du inte ska lägga till fler uppgifter om placering etc.

För att lägga till fler uppgifter, gå till fälten Klassifikation (hylla) och eller Löpnummer. Placeringsuppgift registreras enligt praxis vid ditt bibliotek.

Klassifikationskoden kan kompletteras med ytterligare placeringsuppgifter, t.ex. titel- eller författarord. Klicka på ”Visa fler fält” om respektive uppställningsled behöver särskiljas eller anges i olika fält.

Klicka på ”Visa fler fält” om uppgiften behöver kompletteras med anmärkning.

Klicka på ”Lägg till bestånd för seriella resurser” om uppgiften behöver kompletteras med beståndsanmärkning.

För eventuella exemplar uppställda på annan hylla (motsvarande), eller med med avvikande tillgänglighet, eller uppställda enligt annan placering, eller med annat löpnummer, eller uppställda under annat ord / annan fras, eller uppställda på annan avdelning (motsvarande), klicka på ”Lägg till placeringsfält”.

" 24 | }, 25 | "app:suggestions": { 26 | "comment": "Klicka på lämpligt förslag till höger om inmatningsfältet." 27 | }, 28 | "app:targetScopeOfMaterial": { 29 | "@id": "app:targetScopeOfMaterial", 30 | "label": "Del av materialet som avses", 31 | "comment": "Kan användas för att förtydliga att URI:n (webbadressen) bara avser delar av materialet, t.ex. en innehållsförteckning (table of contents)." 32 | }, 33 | "app:workExampleSomeProducts": { 34 | "@id": "app:workExampleSomeProducts", 35 | "label": "Volymer, häften, nummer etc.", 36 | "comment": "Ange de volymer, häften, nummer etc. som biblioteket har av tidskriften (motsvarande).", 37 | "example": ["1-10", "1-25(1952-1959), 1960-"] 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /source/vocab/bf-map.ttl: -------------------------------------------------------------------------------- 1 | @prefix rdfs: . 2 | @prefix owl: . 3 | @prefix sdo: . 4 | @prefix bf2: . 5 | @prefix kbv: . 6 | 7 | #kbv:Record owl:equivalentClass kbv:AdminMetadata . 8 | 9 | kbv:created owl:equivalentProperty bf2:creationDate . 10 | kbv:modified owl:equivalentProperty bf2:changeDate . 11 | 12 | kbv:identifiedBy rdfs:domain kbv:Creation . 13 | kbv:language rdfs:domain kbv:Creation . 14 | kbv:partOfSeries rdfs:domain kbv:Creation . 15 | kbv:referencedBy rdfs:domain kbv:Creation . 16 | kbv:references rdfs:domain kbv:Creation . 17 | kbv:hasEquivalent rdfs:domain kbv:Creation . 18 | kbv:accompanies rdfs:domain kbv:Creation . 19 | kbv:accompaniedBy rdfs:domain kbv:Creation . 20 | kbv:summary rdfs:domain kbv:Endeavour . 21 | 22 | kbv:hasTitle owl:equivalentProperty bf2:title . 23 | kbv:contentType owl:equivalentProperty bf2:content . 24 | kbv:mediaType owl:equivalentProperty bf2:media . 25 | kbv:carrierType owl:equivalentProperty bf2:carrier . 26 | kbv:ContentType owl:equivalentClass bf2:Content . 27 | kbv:MediaType owl:equivalentClass bf2:Media . 28 | kbv:CarrierType owl:equivalentClass bf2:Carrier . 29 | 30 | kbv:issuanceType owl:equivalentProperty bf2:issuance . 31 | kbv:IssuanceType owl:equivalentClass bf2:Issuance . 32 | 33 | kbv:hasNotation owl:equivalentProperty bf2:notation . 34 | kbv:hasNote owl:equivalentProperty bf2:note . 35 | 36 | kbv:creditsNote owl:equivalentProperty bf2:credits . 37 | kbv:awardsNote owl:equivalentProperty bf2:awards . 38 | 39 | kbv:isPartOf owl:equivalentProperty bf2:partOf . 40 | 41 | kbv:hasPart owl:equivalentProperty bf2:hasPart ; 42 | rdfs:domain kbv:Resource ; # NOTE: loosens implied bf2 domain 43 | rdfs:range kbv:Resource . # NOTE: loosens implied bf2 range 44 | 45 | kbv:relatedTo owl:equivalentProperty bf2:relatedTo ; 46 | rdfs:domain kbv:Resource ; # NOTE: loosens implied bf2 domain 47 | rdfs:range kbv:Resource . # NOTE: loosens implied bf2 range 48 | 49 | kbv:CODEN a rdfs:Datatype; owl:equivalentClass bf2:Coden . 50 | kbv:DOI a rdfs:Datatype; owl:equivalentClass bf2:Doi . 51 | kbv:EAN a rdfs:Datatype; owl:equivalentClass bf2:Ean . 52 | kbv:EIDR a rdfs:Datatype; owl:equivalentClass bf2:Eidr . 53 | kbv:GTIN14 a rdfs:Datatype; owl:equivalentClass bf2:Gtin14Number . 54 | kbv:ISAN a rdfs:Datatype; owl:equivalentClass bf2:Isan . 55 | kbv:ISBN a rdfs:Datatype; owl:equivalentClass bf2:Isbn . 56 | kbv:ISMN a rdfs:Datatype; owl:equivalentClass bf2:Ismn . 57 | kbv:ISNI a rdfs:Datatype; owl:equivalentClass bf2:Isni . 58 | kbv:ISO a rdfs:Datatype; owl:equivalentClass bf2:Iso . 59 | kbv:ISRC a rdfs:Datatype; owl:equivalentClass bf2:Isrc . 60 | kbv:ISSN a rdfs:Datatype; owl:equivalentClass bf2:Issn . 61 | kbv:ISSNL a rdfs:Datatype; owl:equivalentClass bf2:IssnL . 62 | kbv:ISTC a rdfs:Datatype; owl:equivalentClass bf2:Istc . 63 | kbv:ISWC a rdfs:Datatype; owl:equivalentClass bf2:Iswc . 64 | kbv:LCCN a rdfs:Datatype; owl:equivalentClass bf2:Lccn . 65 | kbv:NBN a rdfs:Datatype; owl:equivalentClass bf2:Nbn . 66 | kbv:SICI a rdfs:Datatype; owl:equivalentClass bf2:Sici . 67 | kbv:STRN a rdfs:Datatype; owl:equivalentClass bf2:Strn . 68 | kbv:UPC a rdfs:Datatype; owl:equivalentClass bf2:Upc . 69 | kbv:URN a rdfs:Datatype; owl:equivalentClass bf2:Urn . 70 | 71 | 72 | # TODO: Remove from kbv 73 | # bf2:shelfMark as ObjectProperty 74 | # bf2:shelfMarkDdc 75 | # bf2:shelfMarkLcc 76 | # bf2:shelfMarkUdc 77 | # bf2:shelfMarkNlm 78 | -------------------------------------------------------------------------------- /source/encodingFormat-terms.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | @prefix rdfs: . 3 | @prefix owl: . 4 | @prefix sdo: . 5 | @prefix skos: . 6 | @prefix iana: . 7 | @prefix lcmenc: . 8 | @base . 9 | 10 | # TODO: Add TAR 11 | 12 | a :EncodingFormat ; 13 | rdfs:label "JSON" ; 14 | skos:notation "application/json" ; 15 | skos:exactMatch iana:application\/json . 16 | 17 | a :EncodingFormat ; 18 | rdfs:label "JSON-LD" ; 19 | skos:notation "application/ld+json" ; 20 | skos:exactMatch iana:application\/ld\+json . 21 | 22 | a :EncodingFormat ; 23 | rdfs:label "MARC" ; 24 | skos:notation "application/marc" ; 25 | skos:exactMatch iana:application\/marc . 26 | 27 | a :EncodingFormat ; 28 | rdfs:label "MARCXML" ; 29 | skos:notation "application/marcxml+xml" ; 30 | skos:exactMatch iana:application\/marcxml\+xml . 31 | 32 | a :EncodingFormat ; 33 | rdfs:label "MSWord" ; 34 | skos:notation "application/msword" ; 35 | skos:exactMatch iana:application\/msword . 36 | 37 | a :EncodingFormat ; 38 | rdfs:label "PDF" ; 39 | skos:notation "application/pdf" ; 40 | skos:exactMatch iana:application\/pdf . 41 | 42 | a :EncodingFormat ; 43 | rdfs:label "RDF/XML" ; 44 | skos:notation "application/rdf+xml" ; 45 | skos:exactMatch iana:application\/rdf\+xml . 46 | 47 | a :EncodingFormat ; 48 | rdfs:label "ZIP" ; 49 | skos:notation "application/zip" ; 50 | skos:exactMatch iana:application\/zip . 51 | 52 |