fix(serialize-xml): compact serialization when easily possible

This commit is contained in:
Johannes Frohnmeyer 2024-04-20 15:20:26 +02:00
parent 0f8a549495
commit 846bb1a982
Signed by: Johannes
GPG Key ID: E76429612C2929F4
1 changed files with 43 additions and 10 deletions

View File

@ -26,6 +26,7 @@ public class NativeXmlWriter implements Closeable, Flushable {
private boolean usesEmptyNewlineAndIndent; private boolean usesEmptyNewlineAndIndent;
private final List<String> deferredComments = new LinkedList<>(); private final List<String> deferredComments = new LinkedList<>();
private String deferredText = null;
private boolean wasText = false; private boolean wasText = false;
private boolean lenient; private boolean lenient;
@ -103,22 +104,42 @@ public class NativeXmlWriter implements Closeable, Flushable {
throw new IllegalStateException("Nesting problem."); throw new IllegalStateException("Nesting problem.");
} }
wasText = false; wasText = false;
boolean simple = false; // true if the last tag only contained simple text
if (!deferredComments.isEmpty()) { if (!deferredComments.isEmpty()) {
beforeValue(); if (context == TAG_HEAD && deferredComments.size() == 1) {
newline(); out.write('>');
writeDeferredComment(); if (deferredText == null) simple = true;
else newline();
writeDeferredComment();
} else {
if (context == TAG_HEAD) out.write('>');
newline();
writeDeferredComment();
}
context = TAG_BODY; context = TAG_BODY;
} }
if (deferredText != null) {
if (context == TAG_HEAD) {
out.write('>');
escapeText(deferredText, true);
context = TAG_BODY;
simple = true;
} else text(deferredText);
deferredText = null;
}
stackSize--; stackSize--;
if (context == TAG_BODY) { if (context == TAG_BODY) {
newline(); if (!simple) newline();
out.write("</");
name(pathNames[stackSize - 1]);
out.write('>');
} else {
out.write("/>");
} }
out.write("</");
name(pathNames[stackSize - 1]);
pathNames[stackSize - 1] = null; pathNames[stackSize - 1] = null;
out.write('>');
return this; return this;
} }
@ -208,6 +229,10 @@ public class NativeXmlWriter implements Closeable, Flushable {
} }
public NativeXmlWriter text(String text) throws IOException { public NativeXmlWriter text(String text) throws IOException {
if (peek() == TAG_HEAD && !text.contains("\n") && deferredComments.isEmpty()) {
deferredText = text;
return this;
}
text = text == null ? "" : text; text = text == null ? "" : text;
if (wasText) comment(""); if (wasText) comment("");
beforeValue(); beforeValue();
@ -262,7 +287,6 @@ public class NativeXmlWriter implements Closeable, Flushable {
private void name(String name) throws IOException { private void name(String name) throws IOException {
if (name == null) throw new NullPointerException("name == null"); if (name == null) throw new NullPointerException("name == null");
if (stackSize == 0) throw new IllegalStateException("JsonWriter is closed."); if (stackSize == 0) throw new IllegalStateException("JsonWriter is closed.");
if (peek() != TAG_HEAD) throw new IllegalStateException("Nesting problem.");
// Check name for illegal characters // Check name for illegal characters
int last = 0; int last = 0;
int length = name.length(); int length = name.length();
@ -283,7 +307,6 @@ public class NativeXmlWriter implements Closeable, Flushable {
case FIRST -> {} case FIRST -> {}
} }
} }
out.write(' ');
if (last < length) out.write(name, last, length - last); if (last < length) out.write(name, last, length - last);
} }
@ -329,8 +352,13 @@ public class NativeXmlWriter implements Closeable, Flushable {
case EMPTY_DOCUMENT: case EMPTY_DOCUMENT:
replaceTop(NONEMPTY_DOCUMENT); replaceTop(NONEMPTY_DOCUMENT);
if (!deferredComments.isEmpty()) { if (!deferredComments.isEmpty()) {
newline();
writeDeferredComment(); writeDeferredComment();
newline();
}
if (deferredText != null) {
escapeText(deferredText, true);
newline();
deferredText = null;
} }
break; break;
case DANGLING_NAME: case DANGLING_NAME:
@ -343,6 +371,11 @@ public class NativeXmlWriter implements Closeable, Flushable {
replaceTop(TAG_BODY); replaceTop(TAG_BODY);
case TAG_BODY: case TAG_BODY:
newline(); newline();
if (deferredText != null) {
escapeText(deferredText, true);
newline();
deferredText = null;
}
if (!deferredComments.isEmpty()) { if (!deferredComments.isEmpty()) {
writeDeferredComment(); writeDeferredComment();
newline(); newline();