feat(serialize-xml): make whitespace handling and leniency configurable

This commit is contained in:
Johannes Frohnmeyer 2024-04-13 20:06:02 +02:00
parent 264f847cdf
commit 866b429155
Signed by: Johannes
GPG Key ID: E76429612C2929F4
1 changed files with 21 additions and 6 deletions

View File

@ -74,7 +74,8 @@ public class BaseXmlReader implements Closeable {
private String[] pathNames = new String[32]; private String[] pathNames = new String[32];
private int[] pathIndices = new int[32]; private int[] pathIndices = new int[32];
private boolean lenient = false; // TODO: make this configurable private boolean lenient = false;
private boolean skipWhitespace = true;
public BaseXmlReader(Reader in) { public BaseXmlReader(Reader in) {
this.in = Objects.requireNonNull(in, "in == null"); this.in = Objects.requireNonNull(in, "in == null");
} }
@ -88,6 +89,15 @@ public class BaseXmlReader implements Closeable {
return lenient; return lenient;
} }
public BaseXmlReader setSkipWhitespace(boolean skipWhitespace) {
this.skipWhitespace = skipWhitespace;
return this;
}
public boolean isSkipWhitespace() {
return skipWhitespace;
}
private void push(int newTop) { private void push(int newTop) {
if (stackSize == stack.length) { if (stackSize == stack.length) {
int newLength = stackSize * 2; int newLength = stackSize * 2;
@ -231,9 +241,9 @@ public class BaseXmlReader implements Closeable {
} else if (peekStack == XmlScope.DANGLING_NAME) { } else if (peekStack == XmlScope.DANGLING_NAME) {
stack[stackSize - 1] = XmlScope.TAG_HEAD; stack[stackSize - 1] = XmlScope.TAG_HEAD;
// Look for an equals sign before the value // Look for an equals sign before the value
int c = nextNonWhitespace(true); int c = lenient ? nextNonWhitespace(true) : buffer[pos++];
if (c == '=') { if (c == '=') {
c = nextNonWhitespace(true); c = lenient ? nextNonWhitespace(true) : buffer[pos++];
if (c == '\'' || c == '"') { if (c == '\'' || c == '"') {
return peeked = PEEKED_ATTRIBUTE_VALUE; return peeked = PEEKED_ATTRIBUTE_VALUE;
} else { } else {
@ -248,7 +258,7 @@ public class BaseXmlReader implements Closeable {
stack[stackSize - 1] = XmlScope.NONEMPTY_DOCUMENT; stack[stackSize - 1] = XmlScope.NONEMPTY_DOCUMENT;
// fall through: a new element is starting // fall through: a new element is starting
} else if (peekStack == XmlScope.NONEMPTY_DOCUMENT) { } else if (peekStack == XmlScope.NONEMPTY_DOCUMENT) {
int c = nextNonWhitespace(false); int c = skipWhitespace ? nextNonWhitespace(false) : buffer[pos++];
if (c == -1) { if (c == -1) {
return peeked = PEEKED_EOF; return peeked = PEEKED_EOF;
} else { } else {
@ -259,7 +269,7 @@ public class BaseXmlReader implements Closeable {
} else if (peekStack == XmlScope.CLOSED) { } else if (peekStack == XmlScope.CLOSED) {
throw new IllegalStateException("BaseXmlReader is closed"); throw new IllegalStateException("BaseXmlReader is closed");
} }
int c = nextNonWhitespace(true); int c = skipWhitespace ? nextNonWhitespace(true) : buffer[pos++];
if (c == -1) { if (c == -1) {
throw syntaxError("Unterminated tag"); throw syntaxError("Unterminated tag");
} else if (c == '<') { } else if (c == '<') {
@ -442,7 +452,12 @@ public class BaseXmlReader implements Closeable {
if (p != PEEKED_TEXT) { if (p != PEEKED_TEXT) {
throw unexpectedTokenError("TEXT"); throw unexpectedTokenError("TEXT");
} }
return readUntil((c, i) -> c == '<', true); String result = readUntil((c, i) -> c == '<', true);
if (skipWhitespace) {
result = result.trim();
}
peeked = PEEKED_NONE;
return result;
} }
public String nextCData() throws IOException { public String nextCData() throws IOException {