diff --git a/lib/rdf/serializations/turtle_decoder.ex b/lib/rdf/serializations/turtle_decoder.ex index 787b68d..db4cb43 100644 --- a/lib/rdf/serializations/turtle_decoder.ex +++ b/lib/rdf/serializations/turtle_decoder.ex @@ -63,11 +63,26 @@ defmodule RDF.Turtle.Decoder do end defp directive({:prefix, {:prefix_ns, _, ns}, iri}, state) do - State.add_namespace(state, ns, iri) + if RDF.URI.Helper.absolute_iri?(iri) do + State.add_namespace(state, ns, iri) + else + with absolute_uri = RDF.URI.Helper.absolute_iri(iri, state.base_uri) do + State.add_namespace(state, ns, URI.to_string(absolute_uri)) + end + end end - defp directive({:base, uri}, state) do - %State{state | base_uri: RDF.uri(uri)} + defp directive({:base, uri}, %State{base_uri: base_uri} = state) do + cond do + RDF.URI.Helper.absolute_iri?(uri) -> + %State{state | base_uri: RDF.uri(uri)} + base_uri != nil -> + with absolute_uri = RDF.URI.Helper.absolute_iri(uri, base_uri) do + %State{state | base_uri: absolute_uri} + end + true -> + raise "Could not resolve resolve relative IRI '#{uri}', no base uri provided" + end end diff --git a/lib/rdf/uri_helper.ex b/lib/rdf/uri_helper.ex index 0e2ff04..3ef55fe 100644 --- a/lib/rdf/uri_helper.ex +++ b/lib/rdf/uri_helper.ex @@ -17,13 +17,29 @@ defmodule RDF.URI.Helper do characters are treated in URI references, per [section 6.5 of RFC3987](http://tools.ietf.org/html/rfc3987#section-6.5) """ def absolute_iri(value, base_iri) do - case URI.parse(value) do - # absolute? - uri = %URI{scheme: scheme} when not is_nil(scheme) -> uri - # relative - _ when is_nil(base_iri) -> nil - _ -> URI.merge(base_iri, value) + uri = + case URI.parse(value) do + # absolute? + uri = %URI{scheme: scheme} when not is_nil(scheme) -> uri + # relative + _ when is_nil(base_iri) -> nil + _ -> URI.merge(base_iri, value) + end + if String.ends_with?(value, "#") do + %URI{uri | fragment: ""} + else + uri end end + @doc """ + Checks if the given value is an absolute IRI. + + An absolute IRI is defined in [RFC3987](http://www.ietf.org/rfc/rfc3987.txt) + containing a scheme along with a path and optional query and fragment segments. + + see + """ + def absolute_iri?(value), do: RDF.uri?(value) + end