diff --git a/src/main/java/org/apache/xmlbeans/impl/store/Saver.java b/src/main/java/org/apache/xmlbeans/impl/store/Saver.java
index 5a7fe94c6..4dd999437 100755
--- a/src/main/java/org/apache/xmlbeans/impl/store/Saver.java
+++ b/src/main/java/org/apache/xmlbeans/impl/store/Saver.java
@@ -547,7 +547,7 @@ private void pushMappings(SaveCur c, boolean ensureDefaultEmpty) {
}
private void addNewFrameMapping(String prefix, String uri, boolean ensureDefaultEmpty) {
- // If the prefix maps to "", then don't include this mapping 'cause it's not well formed.
+ // If the prefix maps to "", then don't include this mapping 'cause it's not well-formed.
// Also, if we want to make sure that the default namespace is always "", then check that
// here as well.
@@ -562,7 +562,7 @@ private void addNewFrameMapping(String prefix, String uri, boolean ensureDefault
}
// Also make sure that the prefix declaration is not redundant
- // This has the side-effect of making it impossible to set a
+ // This has the side effect of making it impossible to set a
// redundant prefix declaration, but seems that it's better
// to just never issue a duplicate prefix declaration.
if (uri.equals(getNamespaceForPrefix(prefix))) {
@@ -1413,7 +1413,7 @@ private void entitizeComment() {
i = replace(i, "?");
} else if (ch == '-') {
if (lastWasDash) {
- // Replace "--" with "- " to make well formed
+ // Replace "--" with "- " to make well-formed
i = replace(i, " ");
lastWasDash = false;
} else {
@@ -1452,11 +1452,12 @@ private void entitizeProcinst() {
char ch = _cbuf[i];
if (isBadChar(ch)) {
- i = replace(i, "?");
+ replace(i, "?");
+ ch = '?';
}
if (ch == '>') {
- // TODO - Had to convert to a space here ... imples not well formed XML
+ // TODO - Had to convert to a space here ... implies not well-formed XML
if (lastWasQuestion) {
i = replace(i, " ");
} else {
@@ -2141,7 +2142,7 @@ private void entitizeAndWriteCommentText(int bufLimit) {
_buf[i] = '?';
} else if (ch == '-') {
if (lastWasDash) {
- // Replace "--" with "- " to make well formed
+ // Replace "--" with "- " to make well-formed
_buf[i] = ' ';
lastWasDash = false;
} else {
@@ -2175,7 +2176,7 @@ private void entitizeAndWritePIText(int bufLimit) {
}
if (ch == '>') {
- // Had to convert to a space here ... imples not well formed XML
+ // Had to convert to a space here ... implies not well-formed XML
if (lastWasQuestion) {
_buf[i] = ' ';
}
diff --git a/src/test/java/misc/checkin/ProcInstEscapeTest.java b/src/test/java/misc/checkin/ProcInstEscapeTest.java
new file mode 100644
index 000000000..66358c199
--- /dev/null
+++ b/src/test/java/misc/checkin/ProcInstEscapeTest.java
@@ -0,0 +1,67 @@
+/* Copyright 2004 The Apache Software Foundation
+ *
+ * Licensed 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,
+ * 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 misc.checkin;
+
+import org.apache.xmlbeans.XmlCursor;
+import org.apache.xmlbeans.XmlObject;
+import org.apache.xmlbeans.XmlOptions;
+import org.junit.jupiter.api.Test;
+
+import java.io.StringWriter;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
+public class ProcInstEscapeTest {
+
+ private static XmlObject docWithProcInst(String piText) throws Exception {
+ XmlObject o = XmlObject.Factory.parse("x");
+ try (XmlCursor c = o.newCursor()) {
+ c.toNextToken();
+ c.toNextToken();
+ c.insertProcInst("tgt", piText);
+ }
+ return o;
+ }
+
+ private static String saveForSpeed(XmlObject o) throws Exception {
+ XmlOptions opts = new XmlOptions();
+ opts.setSaveOptimizeForSpeed(true);
+ StringWriter sw = new StringWriter();
+ o.save(sw, opts);
+ return sw.toString();
+ }
+
+ // a bad char immediately before "?>" used to make the default saver skip the
+ // "?>" so it survived inside the processing instruction
+ @Test
+ void testBadCharBeforePiEnd() throws Exception {
+ XmlObject o = docWithProcInst("\u0007?>");
+ String out = o.xmlText();
+ assertEquals("x", out);
+ // the only "?>" in the output is the PI terminator
+ assertFalse(out.substring(0, out.indexOf("?>x")).contains("?>"));
+ // round-trips and both savers agree
+ XmlObject.Factory.parse(out);
+ assertEquals(out, saveForSpeed(o));
+ }
+
+ @Test
+ void testPlainQuestionGtStillEscaped() throws Exception {
+ XmlObject o = docWithProcInst("a?>b");
+ assertEquals("x", o.xmlText());
+ }
+}