This is an automated email from the ASF dual-hosted git repository.

andy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/jena.git


The following commit(s) were added to refs/heads/main by this push:
     new a3f605c194 GH-2619: Fix writing invalid rdf:XMLLiterals
a3f605c194 is described below

commit a3f605c19429ef2ed9f46ddd3b1e6bb942e786b6
Author: Andy Seaborne <[email protected]>
AuthorDate: Tue Aug 6 15:57:23 2024 +0100

    GH-2619: Fix writing invalid rdf:XMLLiterals
---
 .../org/apache/jena/riot/writer/TS_RiotWriter.java |  5 +-
 .../apache/jena/riot/writer/TestWriterRDFXML.java  | 70 ++++++++++++++++++++++
 ...rties.java => TestWriterRDFXML_Properties.java} |  2 +-
 .../jena/rdfxml/xmloutput/impl/Unparser.java       |  6 +-
 4 files changed, 79 insertions(+), 4 deletions(-)

diff --git 
a/jena-arq/src/test/java/org/apache/jena/riot/writer/TS_RiotWriter.java 
b/jena-arq/src/test/java/org/apache/jena/riot/writer/TS_RiotWriter.java
index 7cab9dc100..a65492e2d8 100644
--- a/jena-arq/src/test/java/org/apache/jena/riot/writer/TS_RiotWriter.java
+++ b/jena-arq/src/test/java/org/apache/jena/riot/writer/TS_RiotWriter.java
@@ -24,14 +24,15 @@ import org.junit.runners.Suite.SuiteClasses ;
 
 @RunWith(Suite.class)
 @SuiteClasses(
-{ 
+{
     TestWriterRegistration.class
     , TestRiotWriterGraph.class
     , TestRiotWriterDataset.class
     , TestRDFJSON.class
     , TestTurtleWriter.class
     , TestTriXWriter.class
-    , TestRDFXML_WriterProperties.class
+    , TestWriterRDFXML.class
+    , TestWriterRDFXML_Properties.class
 })
 
 public class TS_RiotWriter
diff --git 
a/jena-arq/src/test/java/org/apache/jena/riot/writer/TestWriterRDFXML.java 
b/jena-arq/src/test/java/org/apache/jena/riot/writer/TestWriterRDFXML.java
new file mode 100644
index 0000000000..d416562ef6
--- /dev/null
+++ b/jena-arq/src/test/java/org/apache/jena/riot/writer/TestWriterRDFXML.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" 
BASIS,rdf:parseType="Literal"
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.riot.writer;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.apache.jena.atlas.logging.LogCtl;
+import org.apache.jena.graph.Graph;
+import org.apache.jena.rdf.model.ModelFactory;
+import org.apache.jena.riot.*;
+import org.apache.jena.vocabulary.RDF;
+import org.apache.jena.vocabulary.RDFS;
+import org.junit.Test;
+
+/**
+ * Additional tests for RDF/XML writing.
+ */
+public class TestWriterRDFXML {
+    @Test public void testRDFXMLLIterals_1() {
+        // Valid RDF XMLLiteral.
+        testXMLLiteral("<ns:text xmlns:ns='http://example/ns#'>ABC</ns:text>", 
true);
+    }
+
+    @Test public void testRDFXMLLIterals_2() {
+        // Valid RDF XMLLiteral. Document fragment.
+        testXMLLiteral("<ns:text 
xmlns:ns='http://example/ns#'>ABC</ns:text><content>XYZ</content>", true);
+    }
+
+    @Test public void testRDFXMLLIterals_bad_1() {
+        // Invalid RDF XMLLiteral. Not self contained XML - no namespaces
+        testXMLLiteral("<ns:text>ABC</ns:text>", false);
+    }
+
+    @Test public void testRDFXMLLIterals_bad_2() {
+        // Invalid RDF XMLLiteral. Not valid XML - no namespaces
+        testXMLLiteral("<ns:text>ABC", false);
+    }
+
+    private static void testXMLLiteral(String lex, boolean expectValid) {
+        var m = ModelFactory.createDefaultModel();//createOntologyModel();
+        m.createResource().addProperty(RDFS.comment, m.createTypedLiteral(lex, 
RDF.dtXMLLiteral));
+        String s = 
RDFWriter.source(m).format(RDFFormat.RDFXML_ABBREV).toString();
+
+        // Valid RDF XML Literal - write as rdf:parseType Literal
+        // Invalid RDF XML Literal - write as rdf:datatype
+
+        assertEquals(expectValid, s.contains("rdf:parseType=\"Literal\""));
+        assertEquals(expectValid, ! s.contains("rdf:datatype="));
+
+        LogCtl.withLevel(SysRIOT.getLogger(), "ERROR", ()->{
+            Graph g = RDFParser.fromString(s, Lang.RDFXML).toGraph();
+        });
+    }
+}
diff --git 
a/jena-arq/src/test/java/org/apache/jena/riot/writer/TestRDFXML_WriterProperties.java
 
b/jena-arq/src/test/java/org/apache/jena/riot/writer/TestWriterRDFXML_Properties.java
similarity index 98%
rename from 
jena-arq/src/test/java/org/apache/jena/riot/writer/TestRDFXML_WriterProperties.java
rename to 
jena-arq/src/test/java/org/apache/jena/riot/writer/TestWriterRDFXML_Properties.java
index b9ce3c336a..124487f28a 100644
--- 
a/jena-arq/src/test/java/org/apache/jena/riot/writer/TestRDFXML_WriterProperties.java
+++ 
b/jena-arq/src/test/java/org/apache/jena/riot/writer/TestWriterRDFXML_Properties.java
@@ -31,7 +31,7 @@ import org.junit.Assert ;
 import org.junit.Test ;
 
 /** Tests of the RDF/XML writers used via RIOT */
-public class TestRDFXML_WriterProperties {
+public class TestWriterRDFXML_Properties {
 
     static Model model = ModelFactory.createDefaultModel() ;
     static {
diff --git 
a/jena-core/src/main/java/org/apache/jena/rdfxml/xmloutput/impl/Unparser.java 
b/jena-core/src/main/java/org/apache/jena/rdfxml/xmloutput/impl/Unparser.java
index db7e80fca1..cd0dc4954c 100644
--- 
a/jena-core/src/main/java/org/apache/jena/rdfxml/xmloutput/impl/Unparser.java
+++ 
b/jena-core/src/main/java/org/apache/jena/rdfxml/xmloutput/impl/Unparser.java
@@ -428,13 +428,17 @@ class Unparser {
      * propName '>'
      */
     private boolean wPropertyEltLiteral(WType wt, Property prop, Statement 
statement, RDFNode rdfNode) {
+        // Is the rule blocked?
         if (prettyWriter.sParseTypeLiteralPropertyElt)
             return false;
         if ( ! (rdfNode instanceof Literal lit) )
             return false;
-
         if (! XMLLiteralType.isXMLLiteral(lit.getDatatype()) )
             return false;
+        // Must be a legal XML fragment.
+        // It must be valid XML and also self-contained XML content (e.g. 
includes namespaces - they are not inherited from the model).
+        if ( ! lit.asNode().getLiteral().isWellFormed() )
+            return false;
 
         // print out.
         done(statement);

Reply via email to