diff --git a/src/main/java/fr/inria/corese/core/next/data/api/support/term/IRIUtils.java b/src/main/java/fr/inria/corese/core/next/data/api/support/term/IRIUtils.java index b629c1d79..0873cf08a 100644 --- a/src/main/java/fr/inria/corese/core/next/data/api/support/term/IRIUtils.java +++ b/src/main/java/fr/inria/corese/core/next/data/api/support/term/IRIUtils.java @@ -121,8 +121,8 @@ public static String guessLocalName(String iri) { if (matcher == null || !matcher.matches()) { return iri; } else if (matcher.matches()) { - if (matcher.group("fragment") != null) { // If the IRI has a fragment - return matcher.group("fragment"); + if (matcher.group("anchor") != null) { + return matcher.group("fragment") != null ? matcher.group("fragment") : ""; } else if (matcher.group(FINAL_PATH_GROUP) != null) { // If the IRI has no fragment but does not end with a slash return matcher.group(FINAL_PATH_GROUP); } else { // If the URI ends with a slash diff --git a/src/main/java/fr/inria/corese/core/next/data/impl/io/parser/rdfa/RDFaParser.java b/src/main/java/fr/inria/corese/core/next/data/impl/io/parser/rdfa/RDFaParser.java index 6d187f56f..ea9b51c29 100644 --- a/src/main/java/fr/inria/corese/core/next/data/impl/io/parser/rdfa/RDFaParser.java +++ b/src/main/java/fr/inria/corese/core/next/data/impl/io/parser/rdfa/RDFaParser.java @@ -46,8 +46,8 @@ public class RDFaParser extends AbstractRDFParser { private String baseIri = IOConstants.getDefaultBaseURI(); - private SAXParser saxParser; - private SAXParserFactory saxParserFactory; + private final SAXParser saxParser; + private final SAXParserFactory saxParserFactory; /** * An index of IRI prefixes @@ -249,7 +249,13 @@ && isAttributePresent(RDFaAttributes.HREF)) { throw new ParsingException("Prefix '" + prefixName + "' contains underscore character which is not allowed in xmlns declaration"); } - IRI prefixNamespace = getValueFactory().createIRI(attributeValue, ""); + IRI prefixNamespace; + if (IRIUtils.isStandardIRI(attributeValue)) { + prefixNamespace = getValueFactory().createIRI(attributeValue); + } else { + String baseIriString = currentProcessingContext().getEvaluationContext().getBaseIri().stringValue(); + prefixNamespace = getValueFactory().createIRI(baseIriString + attributeValue); + } this.addIriMapping(prefixName, prefixNamespace); } }); diff --git a/src/main/java/fr/inria/corese/core/next/data/impl/io/parser/support/AbstractTurtleTriGListener.java b/src/main/java/fr/inria/corese/core/next/data/impl/io/parser/support/AbstractTurtleTriGListener.java index 665ae131a..79ee33620 100644 --- a/src/main/java/fr/inria/corese/core/next/data/impl/io/parser/support/AbstractTurtleTriGListener.java +++ b/src/main/java/fr/inria/corese/core/next/data/impl/io/parser/support/AbstractTurtleTriGListener.java @@ -138,6 +138,11 @@ public String resolveIRI(String raw) { } else if (isAbsoluteIRI(raw)) { return raw; } else { + if (prefix.isEmpty()) { + throw new ParsingException( + "Undeclared prefix: '' (empty prefix). " + + "Use '@prefix : .' to declare it."); + } throw new ParsingException("Undeclared prefix: " + prefix); } } diff --git a/src/test/java/fr/inria/corese/core/next/data/impl/io/parser/rdfa/RDFaParserTest.java b/src/test/java/fr/inria/corese/core/next/data/impl/io/parser/rdfa/RDFaParserTest.java index f383ebb58..63b8abb3b 100644 --- a/src/test/java/fr/inria/corese/core/next/data/impl/io/parser/rdfa/RDFaParserTest.java +++ b/src/test/java/fr/inria/corese/core/next/data/impl/io/parser/rdfa/RDFaParserTest.java @@ -511,6 +511,32 @@ void test429ErrorOnDTD() { assertTrue(testModel.contains(subject, RDF.type.getIRI(), object)); } + @Test + void parseXmlnsWithRelativeUri() { + String xhtml = """ + + + + +

Alice

+ + """; + + Model model = createTestModel(); + RDFParser parser = parserFactory.createRDFParser(RDFFormat.RDFA, model, valueFactory); + parser.parse(new ByteArrayInputStream(xhtml.getBytes()), "http://example.org/test/"); + + IRI subject = valueFactory.createIRI("http://example.org/test/#me"); + IRI type = RDF.type.getIRI(); + IRI personClass = valueFactory.createIRI("http://example.org/test/vocab#Person"); + IRI namePred = valueFactory.createIRI("http://example.org/test/vocab#name"); + + assertTrue(model.contains(subject, type, personClass)); + assertTrue(model.contains(subject, namePred, valueFactory.createLiteral("Alice"))); + } + private static void logModelContent(Model model) { StringWriter outWriter = new StringWriter(); RDFSerializer serializer = (new DefaultRDFSerializerFactory()).createSerializer(RDFFormat.TURTLE, model); diff --git a/src/test/java/fr/inria/corese/core/next/data/impl/io/parser/turtle/TurtleParserTest.java b/src/test/java/fr/inria/corese/core/next/data/impl/io/parser/turtle/TurtleParserTest.java index ce0c3be91..c1749b7a6 100644 --- a/src/test/java/fr/inria/corese/core/next/data/impl/io/parser/turtle/TurtleParserTest.java +++ b/src/test/java/fr/inria/corese/core/next/data/impl/io/parser/turtle/TurtleParserTest.java @@ -114,4 +114,17 @@ void testRdfaManifest() { assertEquals(refModel.size(), model.size()); } + @Test + void testUndeclaredEmptyPrefixThrowsParsingException() { + String turtle = ":subject :predicate :object ."; + Model model = createTestModel(); + RDFParser parser = new TurtleParser(model, factory); + + fr.inria.corese.core.next.data.api.exception.ParsingException ex = org.junit.jupiter.api.Assertions.assertThrows( + fr.inria.corese.core.next.data.api.exception.ParsingException.class, + () -> parser.parse(new StringReader(turtle)) + ); + assertTrue(ex.getMessage().contains("Undeclared prefix: '' (empty prefix)")); + } + }