[DEV] refacto separate serializer, parser and model is OK ==> sax reader is OK not the sax generator (API not open)

This commit is contained in:
Edouard DUPIN 2021-02-26 00:13:25 +01:00
parent d16f4c95e3
commit f610c366ba
29 changed files with 481 additions and 404 deletions

View File

@ -6,6 +6,10 @@
open module org.atriasoft.exml {
exports org.atriasoft.exml;
exports org.atriasoft.exml.model;
exports org.atriasoft.exml.exception;
exports org.atriasoft.exml.builder;
exports org.atriasoft.exml.parser;
requires transitive org.atriasoft.etk;
requires transitive io.scenarium.logger;

View File

@ -9,8 +9,13 @@ package org.atriasoft.exml;
import org.atriasoft.exml.builder.Builder;
import org.atriasoft.exml.builder.BuilderGeneric;
import org.atriasoft.exml.exception.ExmlBuilderException;
import org.atriasoft.exml.exception.ExmlParserErrorMulti;
import org.atriasoft.exml.internal.Log;
import org.atriasoft.exml.model.XmlElement;
import org.atriasoft.exml.model.XmlNode;
import org.atriasoft.exml.parser.ParseXml;
import org.atriasoft.exml.parser.ParsingProperty;
import org.atriasoft.exml.serializer.SerializerXml;
public class Exml {
/**
@ -28,35 +33,21 @@ public class Exml {
* @return false : An error occured
* @return true : Parsing is OK
*/
public static boolean generate(final StringBuilder _data) {
//return iGenerate(_data, 0);
return false;
}
public static boolean iGenerate(final StringBuilder _data, final int _indent) {
/*
for (int iii = 0; iii < this.listSub.size(); iii++) {
if (this.listSub.get(iii) != null) {
this.listSub.get(iii).iGenerate(_data, _indent);
}
public static void generate(final XmlNode root, final StringBuilder _data) {
if (root.isElement() == false || ((XmlElement) root).getValue().isEmpty() == false) {
SerializerXml.serialize(root, _data, 0);
} else {
SerializerXml.serializeRoot((XmlElement) root, _data);
}
*/
return true;
//return iGenerate(_data, 0);
}
public static XmlNode parse(final String data) {
public static XmlElement parse(final String data) throws ExmlBuilderException, ExmlParserErrorMulti {
final Builder builder = new BuilderGeneric();
final ParseXml parser = new ParseXml(builder);
Object out = null;
try {
out = parser.parse(data);
} catch (final ExmlBuilderException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return (XmlNode) out;
final ParsingProperty property = new ParsingProperty();
property.setDisplayError(true);
return (XmlElement) parser.parse(data, property);
}
/**

View File

@ -1,25 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2021, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
package org.atriasoft.exml;
public class TextCDATA extends XmlText {
public TextCDATA() {
super();
}
public TextCDATA(final String data) {
super(data);
}
@Override
protected boolean iGenerate(final StringBuilder _data, final int _indent) {
_data.append("<![CDATA[");
_data.append(this.value);
_data.append("]]>");
return true;
}
}

View File

@ -1,15 +1,12 @@
/** @file
* @author Edouard DUPIN
* @copyright 2021, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
package org.atriasoft.exml.builder;
import org.atriasoft.exml.exception.ExmlBuilderException;
/**
* @author heero
*
*/
/**
* @author heero
*
*/
public interface Builder {
/**

View File

@ -1,12 +1,17 @@
/** @file
* @author Edouard DUPIN
* @copyright 2021, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
package org.atriasoft.exml.builder;
import org.atriasoft.exml.XmlAttribute;
import org.atriasoft.exml.XmlAttributeList;
import org.atriasoft.exml.XmlComment;
import org.atriasoft.exml.XmlDeclaration;
import org.atriasoft.exml.XmlElement;
import org.atriasoft.exml.XmlText;
import org.atriasoft.exml.exception.ExmlBuilderException;
import org.atriasoft.exml.model.XmlAttribute;
import org.atriasoft.exml.model.XmlAttributeList;
import org.atriasoft.exml.model.XmlComment;
import org.atriasoft.exml.model.XmlDeclaration;
import org.atriasoft.exml.model.XmlElement;
import org.atriasoft.exml.model.XmlText;
public class BuilderGeneric implements Builder {
@ -15,6 +20,7 @@ public class BuilderGeneric implements Builder {
if (element instanceof XmlElement) {
final XmlElement elem = (XmlElement) element;
elem.append(new XmlComment(comment));
return;
}
throw new ExmlBuilderException("can not add Comment on something else than Element");
}

View File

@ -0,0 +1,25 @@
package org.atriasoft.exml.exception;
import org.atriasoft.exml.parser.FilePos;
public class ExmlParserError extends ExmlBuilderException {
private static final long serialVersionUID = 1L;
private final String dataLine; //!< Parse line error (copy);
private final FilePos filePos; //!< position of the error
public ExmlParserError(final String dataLine, final FilePos filePos, final String comment) {
super(comment);
this.dataLine = dataLine;
this.filePos = filePos.clone();
}
public String getDataLine() {
return this.dataLine;
}
public FilePos getFilePos() {
return this.filePos;
}
}

View File

@ -0,0 +1,18 @@
package org.atriasoft.exml.exception;
import java.util.List;
public class ExmlParserErrorMulti extends ExmlBuilderException {
private static final long serialVersionUID = 1L;
private final List<ExmlParserError> errors; // list of errors
public ExmlParserErrorMulti(final String message, final List<ExmlParserError> errors) {
super(message);
this.errors = errors;
}
public List<ExmlParserError> getErrors() {
return this.errors;
}
}

View File

@ -3,9 +3,9 @@
* @copyright 2021, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
package org.atriasoft.exml;
package org.atriasoft.exml.model;
import org.atriasoft.exml.internal.FilePos;
import org.atriasoft.exml.parser.FilePos;
/**
* Single attribute element
@ -68,15 +68,6 @@ public class XmlAttribute {
return this.value;
};
protected boolean iGenerate(final StringBuilder _data, final int _indent) {
_data.append(" ");
_data.append(this.name);
_data.append("=\"");
_data.append(this.value);
_data.append("\"");
return true;
};
/**
* set the name of the attribute
* @param[in] _name New name of the attribute

View File

@ -3,9 +3,10 @@
* @copyright 2021, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
package org.atriasoft.exml;
package org.atriasoft.exml.model;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.ListIterator;
@ -108,7 +109,7 @@ public abstract class XmlAttributeList extends XmlNode {
}
public List<XmlAttribute> getAttributes() {
return this.listAttribute;
return Collections.unmodifiableList(this.listAttribute);
}
/**
@ -122,16 +123,6 @@ public abstract class XmlAttributeList extends XmlNode {
return new Pair<String, String>(att.getName(), att.getValue());
}
@Override
protected boolean iGenerate(final StringBuilder _data, final int _indent) {
for (int iii = 0; iii < this.listAttribute.size(); iii++) {
if (this.listAttribute.get(iii) != null) {
this.listAttribute.get(iii).iGenerate(_data, _indent);
}
}
return true;
}
/**
* Remove an attribute form the list
* @param[in] _name Name of the attribute

View File

@ -3,9 +3,7 @@
* @copyright 2021, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
package org.atriasoft.exml;
import org.atriasoft.exml.internal.Tools;
package org.atriasoft.exml.model;
/**
* Comment node: lt;!-- ... --gt;
@ -38,13 +36,4 @@ public class XmlComment extends XmlNode {
return XmlNodeType.COMMENT;
}
@Override
public boolean iGenerate(final StringBuilder _data, final int _indent) {
Tools.addIndent(_data, _indent);
_data.append("<!--");
_data.append(this.value);
_data.append("-->\n");
return true;
}
};

View File

@ -3,10 +3,9 @@
* @copyright 2021, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
package org.atriasoft.exml;
package org.atriasoft.exml.model;
import org.atriasoft.exml.internal.Log;
import org.atriasoft.exml.internal.Tools;
/**
* Declaration node: lt;?XXXXXX ... gt;
@ -57,16 +56,5 @@ public class XmlDeclaration extends XmlAttributeList {
@Override
public XmlNodeType getType() {
return XmlNodeType.DECLARATION;
};
@Override
protected boolean iGenerate(final StringBuilder _data, final int _indent) {
Tools.addIndent(_data, _indent);
_data.append("<?");
_data.append(this.value);
super.iGenerate(_data, _indent);
_data.append("?>\n");
return true;
}
}

View File

@ -3,15 +3,16 @@
* @copyright 2021, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
package org.atriasoft.exml;
package org.atriasoft.exml.model;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.ListIterator;
import org.atriasoft.exml.exception.ExmlNodeDoesNotExist;
import org.atriasoft.exml.internal.Log;
import org.atriasoft.exml.internal.Tools;
import org.atriasoft.exml.serializer.SerializerXml;
/** @file
* @author Edouard DUPIN
@ -147,12 +148,12 @@ public class XmlElement extends XmlAttributeList {
* @return List of current nodes.
*/
public List<XmlNode> getNodes() {
return this.listSub;
return Collections.unmodifiableList(this.listSub);
}
/**
* get the internal data of the element (if the element has some sub node they are converted in xml string == > like this it is not needed to use <![CDATA[...]]>
* @return the curent data string. if Only one text node, then we get the parssed data (no amp; ...) if more than one node, then we transform ,",',<,> in xml normal text...
* Get the internal data of the element (if the element has some sub node they are converted in xml string == > like this it is not needed to use <![CDATA[...]]>
* @return the current data string. if Only one text node, then we get the parsed data (no amp; ...) if more than one node, then we transform ,",',<,> in xml normal text...
*/
public String getText() {
final StringBuilder res = new StringBuilder();
@ -160,12 +161,12 @@ public class XmlElement extends XmlAttributeList {
if (this.listSub.get(0).getType() == XmlNodeType.TEXT) {
res.append(this.listSub.get(0).getValue());
} else {
this.listSub.get(0).iGenerate(res, 0);
SerializerXml.serialize(this.listSub.get(0), res, 0);
}
} else {
for (int iii = 0; iii < this.listSub.size(); iii++) {
if (this.listSub.get(iii) != null) {
this.listSub.get(iii).iGenerate(res, 0);
SerializerXml.serialize(this.listSub.get(iii), res, 0);
}
}
}
@ -190,36 +191,6 @@ public class XmlElement extends XmlAttributeList {
return this.listSub.get(_id).getType();
}
@Override
protected boolean iGenerate(final StringBuilder _data, final int _indent) {
Tools.addIndent(_data, _indent);
_data.append("<");
_data.append(this.value);
super.iGenerate(_data, _indent);
if (this.listSub.size() > 0) {
if (this.listSub.size() == 1 && this.listSub.get(0) != null && this.listSub.get(0).getType() == XmlNodeType.TEXT && ((XmlText) this.listSub.get(0)).countLines() == 1) {
_data.append(">");
this.listSub.get(0).iGenerate(_data, 0);
Log.verbose(" generate : '" + _data + "'");
} else {
_data.append(">\n");
for (int iii = 0; iii < this.listSub.size(); iii++) {
if (this.listSub.get(iii) != null) {
this.listSub.get(iii).iGenerate(_data, _indent + 1);
}
}
Tools.addIndent(_data, _indent);
}
_data.append("</");
_data.append(this.value);
_data.append(">\n");
} else {
_data.append("/>\n");
}
return true;
}
/**
* Remove all element with this name
* @param[in] _nodeName Name of nodes to remove.

View File

@ -3,63 +3,48 @@
* @copyright 2021, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
package org.atriasoft.exml;
import org.atriasoft.exml.internal.FilePos;
package org.atriasoft.exml.model;
/**
* Basic main object of all xml elements.
*/
public abstract class XmlNode {
protected FilePos pos; //!< position in the read file (null if the file is not parsed)
protected String value; //!< value of the node (for element this is the name, for text it is the inside text ...);
/// Value of the node (for element this is the name, for text it is the inside text ...);
protected String value = "";
/**
* basic element of a xml structure
*/
public XmlNode() {
this.pos = null;
}
public XmlNode() {}
/**
* basic element of a xml structure
* Basic element of a xml structure
* @param[in] _value value of the node
*/
public XmlNode(final String _value) {
this.pos = null;
this.value = _value;
}
/**
* clear the Node
* Clear the Node
*/
public void clear() {
this.value = "";
this.pos = null;
}
@Override
protected XmlNode clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException("Can not clone an abstract class ...");
throw new CloneNotSupportedException("Can not clone an abs ctract class ...");
}
/**
* get the current position where the element is in the file
* @return The file position reference
*/
public FilePos getPos() {
return this.pos;
}
/**
* get the node type.
* Get the node type.
* @return the type of the Node.
*/
public abstract XmlNodeType getType();
/**
* get the current element Value.
* Get the current element Value.
* @return the reference of the string value.
*/
public String getValue() {
@ -67,26 +52,7 @@ public abstract class XmlNode {
}
/**
* generate a string with the tree of the xml
* @param[in,out] _data string where to add the elements
* @param[in] _indent current indentation of the file
* @return false if an error occured.
*/
protected abstract boolean iGenerate(final StringBuilder _data, final int _indent);
/**
* parse the Current node [pure VIRUAL]
* @param[in] _data data string to parse.
* @param[in,out] _pos position in the string to start parse, return the position end of parsing.
* @param[in] _caseSensitive Request a parsion of element that is not case sensitive (all element is in low case)
* @param[in,out] _filePos file parsing position (line x col x)
* @param[in,out] _doc Base document reference
* @return false if an error occured.
*/
//protected abstract boolean iParse(String _data, PositionParsing _pos, boolean _caseSensitive, FilePos _filePos, Document _doc);
/**
* check if the node is a Comment
* Check if the node is a Comment
* @return true if the node is a Comment
*/
public final boolean isComment() {
@ -101,14 +67,6 @@ public abstract class XmlNode {
return this instanceof XmlDeclaration;
}
/**
* check if the node is a Document
* @return true if the node is a Document
*/
public final boolean isDocument() {
return this instanceof Document;
}
/**
* check if the node is a Element
* @return true if the node is a Element
@ -129,7 +87,6 @@ public abstract class XmlNode {
* set the value of the node.
* @param[in] _value New value of the node.
*/
public final void setValue(final String _value) {
this.value = _value;
}
@ -150,14 +107,6 @@ public abstract class XmlNode {
return (XmlDeclaration) this;
}
/**
* Cast the element in a Document if it is possible.
* @return pointer on the class or null.
*/
public final Document toDocument() {
return (Document) this;
}
/**
* Cast the element in a Element if it is possible.
* @return pointer on the class or null.

View File

@ -3,13 +3,12 @@
* @copyright 2021, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
package org.atriasoft.exml;
package org.atriasoft.exml.model;
/**
* Type of the XML elements.
*/
public enum XmlNodeType {
DOCUMENT, //!< all the file main access
DECLARATION, //!< &lt;?xml ... ?&gt;
ELEMENT, //!< the &lt;XXX&gt; ... &lt;/XXX&gt;
COMMENT, //!< comment node : &lt;!-- --&gt;

View File

@ -3,7 +3,7 @@
* @copyright 2021, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
package org.atriasoft.exml;
package org.atriasoft.exml.model;
/**
* Text node interface (internal data between two Marker: &lt;XXX&gt; ALL here &lt;/XXX&gt;
@ -27,7 +27,7 @@ public class XmlText extends XmlNode {
* count the number of line in the current text
* @return The number of lines
*/
protected int countLines() {
public int countLines() {
int count = 1;
for (int iii = 0; iii < this.value.length(); iii++) {
if (this.value.charAt(iii) == '\n') {
@ -40,12 +40,6 @@ public class XmlText extends XmlNode {
@Override
public XmlNodeType getType() {
return XmlNodeType.TEXT;
};
@Override
protected boolean iGenerate(final StringBuilder _data, final int _indent) {
_data.append(replaceSpecialCharOut(this.value));
return true;
}
};

View File

@ -3,7 +3,7 @@
* @copyright 2021, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
package org.atriasoft.exml.internal;
package org.atriasoft.exml.parser;
/** @file
* @author Edouard DUPIN

View File

@ -2,10 +2,9 @@ package org.atriasoft.exml.parser;
import org.atriasoft.exml.builder.Builder;
import org.atriasoft.exml.exception.ExmlBuilderException;
import org.atriasoft.exml.internal.FilePos;
import org.atriasoft.exml.exception.ExmlParserError;
import org.atriasoft.exml.exception.ExmlParserErrorMulti;
import org.atriasoft.exml.internal.Log;
import org.atriasoft.exml.internal.PositionParsing;
import org.atriasoft.exml.internal.Tools;
public class ParseXml {
// global builder that is generate the final Tree
@ -30,27 +29,32 @@ public class ParseXml {
}
}
String name = _data.substring(_pos.value, lastElementName + 1);
String value = "";
if (parsingProperty.getCaseSensitive() == true) {
if (parsingProperty.getStoreMode() == StoreMode.LOWERCASE) {
name = name.toLowerCase();
} else if (parsingProperty.getStoreMode() == StoreMode.UPPERCASE) {
name = name.toUpperCase();
}
// TODO check if in the current list of attribute one is not currently set with this value...
String value = "";
// count white space :
final FilePos tmpPos = new FilePos();
int white = Tools.countWhiteChar(_data, lastElementName + 1, tmpPos);
_filePos.add(tmpPos);
if (lastElementName + white + 1 >= _data.length()) {
parsingProperty.createError(_data, lastElementName + white + 1, _filePos, " parse an xml end with an attribute parsing...");
parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, lastElementName + white + 1), _filePos, " parse an xml end with an attribute parsing..."));
return false;
}
if (_data.charAt(lastElementName + white + 1) != '=') {
parsingProperty.createError(_data, lastElementName + white + 1, _filePos, " error attribute parsing == > missing '=' ...");
parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, lastElementName + white + 1), _filePos, " error attribute parsing == > missing '=' ..."));
return false;
}
white += Tools.countWhiteChar(_data, lastElementName + white + 2, tmpPos);
_filePos.add(tmpPos);
if (lastElementName + white + 2 >= _data.length()) {
parsingProperty.createError(_data, lastElementName + white + 2, _filePos, " parse an xml end with an attribute parsing...");
parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, lastElementName + white + 2), _filePos, " parse an xml end with an attribute parsing..."));
return false;
}
boolean simpleQuoteCase = false;
@ -64,7 +68,7 @@ public class ParseXml {
for (int iii = lastElementName + white + 2; iii < _data.length(); iii++) {
Tools.drawElementParsed(_data.charAt(iii), _filePos);
if (_filePos.check(_data.charAt(iii)) == true) {
parsingProperty.createError(_data, iii, _filePos, "unexpected '\\n' in an attribute parsing");
parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, iii), _filePos, "unexpected '\\n' in an attribute parsing"));
return false;
}
if (_data.charAt(iii) != ' ' && _data.charAt(iii) != '/' && _data.charAt(iii) != '?' && _data.charAt(iii) != '>') {
@ -119,7 +123,7 @@ public class ParseXml {
return true;
}
}
parsingProperty.createError(_data, _pos.value, _filePos, "text CDATA got end of file without finding end node");
parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "text CDATA got end of file without finding end node"));
_pos.value = _data.length();
return false;
}
@ -156,7 +160,7 @@ public class ParseXml {
}
}
_pos.value = _data.length();
parsingProperty.createError(_data, _pos.value, _filePos, "comment got end of file without finding end node");
parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "comment got end of file without finding end node"));
return false;
}
@ -171,7 +175,7 @@ public class ParseXml {
}
if (_data.charAt(iii) == '>' || _data.charAt(iii) == '<') {
// an error occured :
parsingProperty.createError(_data, _pos.value, _filePos, " find '>' or '<' instead of '?>'");
parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, " find '>' or '<' instead of '?>'"));
return false;
}
if (_data.charAt(iii) == '?' && _data.charAt(iii + 1) == '>') {
@ -190,7 +194,7 @@ public class ParseXml {
continue;
}
}
parsingProperty.createError(_data, _pos.value, _filePos, "Text got end of file without finding end node");
parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "Text got end of file without finding end node"));
_pos.value = _data.length();
return false;
}
@ -211,7 +215,7 @@ public class ParseXml {
if (_data.charAt(iii) == '/') {
// standalone node or error...
if (iii + 1 >= _data.length()) {
parsingProperty.createError(_data, _pos.value, _filePos, "Find end of files ... == > bad case");
parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "Find end of files ... == > bad case"));
return false;
}
// TODO : Can have white spaces ....
@ -220,7 +224,7 @@ public class ParseXml {
return true;
}
// error
parsingProperty.createError(_data, _pos.value, _filePos, "Find / without > char ...");
parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "Find / without > char ..."));
return false;
}
if (Tools.checkAvaillable(_data.charAt(iii), true) == true) {
@ -233,11 +237,12 @@ public class ParseXml {
continue;
}
if (Tools.isWhiteChar(_data.charAt(iii)) == false) {
parsingProperty.createError(_data, iii, _filePos, "Find an unknow element : '" + _data.charAt(iii) + "'");
parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, iii), _filePos, "Find an unknow element : '" + _data.charAt(iii) + "'"));
return false;
}
}
parsingProperty.createError(_data, _pos.value, _filePos, "Unexpecting end of parsing exml::internal::Element : '" + nameElement + "' == > check if the '/>' is set or the end of element");
parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos,
"Unexpecting end of parsing exml::internal::Element : '" + nameElement + "' == > check if the '/>' is set or the end of element"));
return false;
}
@ -269,24 +274,26 @@ public class ParseXml {
return true;
}
}
parsingProperty.createError(_data, _pos.value, _filePos, "Text got end of file without finding end node");
parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "Text got end of file without finding end node"));
_pos.value = _data.length();
return false;
}
public Object parse(final String data) throws ExmlBuilderException {
public Object parse(final String data, final ParsingProperty property) throws ExmlBuilderException, ExmlParserErrorMulti {
Log.verbose("Start parsing document (type: string) size=" + data.length());
// came from char == > force in utf8 ...
final FilePos pos = new FilePos(1, 0);
final PositionParsing parsePos = new PositionParsing();
final ParsingProperty property = new ParsingProperty();
final Object rootNode = this.builder.newRoot();
if (subParseElement(rootNode, null, data, parsePos, pos, property) == true) {
return rootNode;
}
return null;
final Object rootNode = this.builder.newRoot();
subParseElement(rootNode, null, data, parsePos, pos, property);
if (property.isErrorDetected() == true) {
if (property.isThrowOnError() == true) {
throw new ExmlParserErrorMulti("Parsing error multiple error detected", property.getErrors());
}
return null;
}
return rootNode;
}
/**
@ -311,14 +318,14 @@ public class ParseXml {
final int white = Tools.countWhiteChar(_data, iii + 1, tmpPos);
if (iii + white + 1 >= _data.length()) {
_filePos.add(tmpPos);
parsingProperty.createError(_data, _pos.value, _filePos, "End file with '<' char == > invalide XML");
parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "End file with '<' char == > invalide XML"));
_pos.value = iii + white;
return false;
}
// Detect type of the element:
if (_data.charAt(iii + white + 1) == '>') {
_filePos.add(tmpPos);
parsingProperty.createError(_data, _pos.value, _filePos, "Find '>' with no element in the element...");
parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "Find '>' with no element in the element..."));
_pos.value = iii + white + 1;
return false;
}
@ -326,7 +333,7 @@ public class ParseXml {
tmpPos.increment();
// TODO : white space ...
if (Tools.checkAvaillable(_data.charAt(iii + white + 2), true) == false) {
parsingProperty.createError(_data, _pos.value, _filePos, "Find unavaillable name in the Declaration node...");
parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "Find unavaillable name in the Declaration node..."));
_pos.value = iii + white + 1;
return false;
}
@ -343,8 +350,10 @@ public class ParseXml {
tmpPos.check(_data.charAt(jjj));
}
String tmpname = _data.substring(iii + white + 2, endPosName + 1);
if (parsingProperty.getCaseSensitive() == true) {
if (parsingProperty.getStoreMode() == StoreMode.LOWERCASE) {
tmpname = tmpname.toLowerCase();
} else if (parsingProperty.getStoreMode() == StoreMode.UPPERCASE) {
tmpname = tmpname.toUpperCase();
}
// Find declaration marker
final Object declaration = this.builder.newDeclaration(parent, tmpname);
@ -361,17 +370,18 @@ public class ParseXml {
tmpPos.increment();
// Find special block element
if (iii + white + 2 >= _data.length()) {
parsingProperty.createError(_data, _pos.value, _filePos, "End file with '<!' chars == > invalide XML");
parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "End file with '<!' chars == > invalide XML"));
return false;
}
if (_data.charAt(iii + white + 2) == '-') {
tmpPos.increment();
if (iii + white + 3 >= _data.length()) {
parsingProperty.createError(_data, _pos.value, _filePos, "End file with '<!-' chars == > invalide XML");
parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "End file with '<!-' chars == > invalide XML"));
return false;
}
if (_data.charAt(iii + white + 3) != '-') {
parsingProperty.createError(_data, _pos.value, _filePos, "Element parse with '<!-" + _data.charAt(iii + 3) + "' chars == > invalide XML");
parsingProperty
.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "Element parse with '<!-" + _data.charAt(iii + 3) + "' chars == > invalide XML"));
return false;
}
tmpPos.increment();
@ -385,13 +395,14 @@ public class ParseXml {
} else if (_data.charAt(iii + white + 2) == '[') {
tmpPos.increment();
if (iii + white + 8 >= _data.length()) {
parsingProperty.createError(_data, _pos.value, _filePos, "End file with '<![' chars == > invalide XML");
parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "End file with '<![' chars == > invalide XML"));
return false;
}
if (_data.charAt(iii + white + 3) != 'C' || _data.charAt(iii + white + 4) != 'D' || _data.charAt(iii + white + 5) != 'A' || _data.charAt(iii + white + 6) != 'T'
|| _data.charAt(iii + white + 7) != 'A' || _data.charAt(iii + white + 8) != '[') {
parsingProperty.createError(_data, _pos.value, _filePos, "Element parse with '<![" + _data.charAt(iii + white + 3) + _data.charAt(iii + white + 4)
+ _data.charAt(iii + white + 5) + _data.charAt(iii + white + 6) + _data.charAt(iii + white + 7) + _data.charAt(iii + white + 8) + "' chars == > invalide XML");
parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos,
"Element parse with '<![" + _data.charAt(iii + white + 3) + _data.charAt(iii + white + 4) + _data.charAt(iii + white + 5) + _data.charAt(iii + white + 6)
+ _data.charAt(iii + white + 7) + _data.charAt(iii + white + 8) + "' chars == > invalide XML"));
return false;
}
tmpPos.add(6);
@ -403,7 +414,8 @@ public class ParseXml {
}
iii = _pos.value;
} else {
parsingProperty.createError(_data, _pos.value, _filePos, "End file with '<!" + _data.charAt(iii + white + 2) + "' chars == > invalide XML");
parsingProperty
.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "End file with '<!" + _data.charAt(iii + white + 2) + "' chars == > invalide XML"));
return false;
}
continue;
@ -422,11 +434,14 @@ public class ParseXml {
}
tmpPos.check(_data.charAt(jjj));
}
String tmpname = _data.substring(iii + white + 2, endPosName + 1);
final String tmpname = _data.substring(iii + white + 2, endPosName + 1);
String tmpnameCheck = tmpname;
String nameElementCheck = nameElement;
if (parsingProperty.getCaseSensitive() == true) {
tmpname = tmpname.toLowerCase();
tmpnameCheck = tmpname.toLowerCase();
nameElementCheck = nameElement.toLowerCase();
}
if (tmpname.contentEquals(nameElement) == true) {
if (tmpnameCheck.contentEquals(nameElementCheck) == true) {
// find end of node :
// find > element ...
for (int jjj = endPosName + 1; jjj < _data.length(); jjj++) {
@ -440,18 +455,19 @@ public class ParseXml {
return true;
} else if (_data.charAt(jjj) != '\r' && _data.charAt(jjj) != ' ' && _data.charAt(jjj) != '\t') {
_filePos.add(tmpPos);
parsingProperty.createError(_data, jjj, _filePos, "End node error : have data inside end node other than [ \\n\\t\\r] " + nameElement + "'");
parsingProperty.createError(
new ExmlParserError(Tools.extractLine(_data, jjj), _filePos, "End node error : have data inside end node other than [ \\n\\t\\r] " + nameElement + "'"));
return false;
}
}
} else {
parsingProperty.createError(_data, _pos.value, _filePos, "End node error : '" + tmpname + "' != '" + nameElement + "'");
parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "End node error : '" + tmpname + "' != '" + nameElement + "'"));
return false;
}
}
if (_data.charAt(iii + white + 1) == '>') {
// end of something == > this is really bad
parsingProperty.createError(_data, _pos.value, _filePos, "Find '>' chars == > invalide XML");
parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "Find '>' chars == > invalide XML"));
return false;
}
@ -470,16 +486,20 @@ public class ParseXml {
tmpPos.check(_data.charAt(jjj));
}
String tmpname = _data.substring(iii + white + 1, endPosName + 1);
if (parsingProperty.getCaseSensitive() == true) {
final String tmpnameOriginal = tmpname;
if (parsingProperty.getStoreMode() == StoreMode.LOWERCASE) {
tmpname = tmpname.toLowerCase();
} else if (parsingProperty.getStoreMode() == StoreMode.UPPERCASE) {
tmpname = tmpname.toUpperCase();
}
Log.debug("find node named : '" + tmpname + "'");
// find text:
final Object element = this.builder.newElement(parent, tmpname);
_pos.value = endPosName + 1;
_filePos.add(tmpPos);
Log.verbose("start parse : 'element' named='" + tmpname + "'");
if (iParseElement(element, tmpname, _data, _pos, _filePos, parsingProperty) == false) {
if (iParseElement(element, tmpnameOriginal, _data, _pos, _filePos, parsingProperty) == false) {
return false;
}
iii = _pos.value;
@ -487,11 +507,11 @@ public class ParseXml {
}
_filePos.add(tmpPos);
// here we have an error :
parsingProperty.createError(_data, _pos.value, _filePos, "Find an ununderstanding element : '" + _data.charAt(iii + white + 1) + "'");
parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "Find an ununderstanding element : '" + _data.charAt(iii + white + 1) + "'"));
return false;
} else {
if (_data.charAt(iii) == '>') {
parsingProperty.createError(_data, _pos.value, _filePos, "Find elemement '>' == > no reason to be here ...");
parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "Find elemement '>' == > no reason to be here ..."));
return false;
}
// might to be data text ...
@ -511,7 +531,7 @@ public class ParseXml {
if (nameElement == null) {
return true;
}
parsingProperty.createError(_data, _pos.value, _filePos, "Did not find end of the exml::internal::Element : '" + nameElement + "'");
parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "Did not find end of the Element : '" + nameElement + "'"));
return false;
}
}

View File

@ -1,54 +1,78 @@
package org.atriasoft.exml.parser;
import org.atriasoft.exml.internal.FilePos;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.atriasoft.exml.exception.ExmlParserError;
import org.atriasoft.exml.internal.Log;
import org.atriasoft.exml.internal.Tools;
public class ParsingProperty {
private boolean caseSensitive; //!< check the case sensitive of the nodes and attribute
private boolean writeErrorWhenDetexted; //!< Request print error in parsing just when detected
private String comment; //!< Comment on the error;
private String Line; //!< Parse line error (copy);
private FilePos filePos; //!< position of the error
/// check the case sensitive of the nodes (end marker) and attribute (duplicates)
private boolean caseSensitive = true;
// Mode to store the Element name or the Attibute name
private StoreMode storeMode = StoreMode.NORMAL;
/// write error when not throw on error.
private boolean writeError = false;
/// throw when an error when it is detected (if permissive XML it throw only at the end of parsing).
private boolean throwOnError = true;
/// Permissive XML parsing (allows some errors must not be critical).
private boolean permisiveXML = false;
// List of all error detected
private final List<ExmlParserError> errors = new ArrayList<>();
/**
* Constructor
*/
public ParsingProperty() {
this.caseSensitive = false;
this.writeErrorWhenDetexted = true;
this.comment = "";
this.Line = "";
this.filePos = new FilePos(0, 0);
public ParsingProperty() {}
/**
* Constructor
* @param caseSensitive set the parsing of value is case sensitive.
* @param writeError Write all error when detected.
* @param throwOnError throw an error when parsing fail (if permissiveXml, it throw only at the end).
* @param permisiveXML Allow error and try to continue the parsing it is possible.
*/
public ParsingProperty(final boolean caseSensitive, final boolean writeError, final boolean throwOnError, final boolean permisiveXML) {
this.caseSensitive = caseSensitive;
this.writeError = writeError;
this.throwOnError = throwOnError;
this.permisiveXML = permisiveXML;
}
/**
* Create an error in the parsing (call by the syetm for error management)
* @param[in] _data string of chat is wrong
* @param[in] _pos Position in the file
* @param[in] _filePos human position of the error
* @param[in] _comment Error string to display
* Add an error in the parsing of the XML (the function will select if we need to throw, print or ...)
* @param error the error to throw or keep.
* @return true if the parsing will stop
* @throws ExmlParserError the error injected if user request it.
*/
public void createError(final String _data, final int _pos, final FilePos _filePos, final String _comment) {
this.comment = _comment;
this.Line = Tools.extract_line(_data, _pos);
this.filePos = _filePos;
if (this.writeErrorWhenDetexted == true) {
displayError();
public boolean createError(final ExmlParserError error) throws ExmlParserError {
// need display the error
if (this.writeError == true) {
displayError(error);
}
// need throw the error
if (this.throwOnError == true && this.permisiveXML == false) {
throw error;
}
// Keep it in case
this.errors.add(error);
return this.permisiveXML == false;
}
/**
* Request Display in log all the errors.
*/
public void displayError() {
this.errors.forEach(o -> displayError(o));
}
/**
* Request display in log of the error
* @param error The error to display.
*/
public void displayError() {
if (this.comment.length() == 0) {
Log.error("No error detected ???");
return;
}
Log.error(this.filePos + " " + this.comment + "\n" + this.Line + "\n" + Tools.createPosPointer(this.Line, this.filePos.getCol()));
//Log.critical("detect error");
public void displayError(final ExmlParserError error) {
Log.error(error.getFilePos() + " " + error.getMessage() + "\n" + error.getDataLine() + "\n" + Tools.createPosPointer(error.getDataLine(), error.getFilePos().getCol()));
}
/**
@ -65,14 +89,53 @@ public class ParsingProperty {
* @return false Does not display error (get it at end)
*/
public boolean getDisplayError() {
return this.writeErrorWhenDetexted;
return this.writeError;
}
/**
* Get all error detected in the XML
* @return Immutable list of error (order by arrival)
*/
public List<ExmlParserError> getErrors() {
return Collections.unmodifiableList(this.errors);
}
/**
* Get the current storing mode
* @return store element and attribute values
*/
public StoreMode getStoreMode() {
return this.storeMode;
}
/**
* Check is error has been detected
* @return true if some error are stored.
*/
public boolean isErrorDetected() {
return this.errors.isEmpty() == false;
}
/**
* Get the permissive value
* @return true if permissive mode is enable
*/
public boolean isPermisiveXML() {
return this.permisiveXML;
}
/**
* Check if throw on error
* @return true if it throw on error
*/
public boolean isThrowOnError() {
return this.throwOnError;
}
/**
* Enable or diasable the case sensitive (must be done before the call of parsing)
* @param[in] _val true if enable; false else.
*/
// TODO: Naming error, it is insensitive ...
public void setCaseSensitive(final boolean _val) {
this.caseSensitive = _val;
}
@ -82,6 +145,30 @@ public class ParsingProperty {
* @param[in] _value true: display error, false not display error (get it at end)
*/
public void setDisplayError(final boolean _value) {
this.writeErrorWhenDetexted = _value;
this.writeError = _value;
}
/**
* Set the permissive value.
* @param permisiveXML new value of permissive parsing.
*/
public void setPermisiveXML(final boolean permisiveXML) {
this.permisiveXML = permisiveXML;
}
/**
* Set the new storing mode for Element and Attributes
* @param storeMode new Storing mode
*/
public void setStoreMode(final StoreMode storeMode) {
this.storeMode = storeMode;
}
/**
* Set throwing on error (if permissive, it throw at the end of parsing)
* @param throwOnError true if it throw on error.
*/
public void setThrowOnError(final boolean throwOnError) {
this.throwOnError = throwOnError;
}
}

View File

@ -1,6 +1,5 @@
package org.atriasoft.exml.internal;
package org.atriasoft.exml.parser;
public class PositionParsing {
public int value = 0;
}

View File

@ -0,0 +1,7 @@
package org.atriasoft.exml.parser;
public enum StoreMode {
NORMAL,
UPPERCASE,
LOWERCASE,
}

View File

@ -1,4 +1,6 @@
package org.atriasoft.exml.internal;
package org.atriasoft.exml.parser;
import org.atriasoft.exml.internal.Log;
public class Tools {
/**
@ -88,7 +90,7 @@ public class Tools {
}
}
public static String extract_line(final String data, final int _pos) {
public static String extractLine(final String data, final int _pos) {
// search back : '\n'
int startPos = data.lastIndexOf('\n', _pos);
if (startPos == _pos) {

View File

@ -0,0 +1,112 @@
package org.atriasoft.exml.serializer;
import java.util.List;
import org.atriasoft.exml.internal.Log;
import org.atriasoft.exml.model.XmlAttribute;
import org.atriasoft.exml.model.XmlAttributeList;
import org.atriasoft.exml.model.XmlComment;
import org.atriasoft.exml.model.XmlDeclaration;
import org.atriasoft.exml.model.XmlElement;
import org.atriasoft.exml.model.XmlNode;
import org.atriasoft.exml.model.XmlNodeType;
import org.atriasoft.exml.model.XmlText;
import org.atriasoft.exml.parser.Tools;
public class SerializerXml {
public static void serialize(final XmlNode node, final StringBuilder data, final int indent) {
if (node instanceof XmlElement) {
serializeElement((XmlElement) node, data, indent);
} else if (node instanceof XmlText) {
serializeText((XmlText) node, data, indent);
} else if (node instanceof XmlDeclaration) {
serializeDeclaration((XmlDeclaration) node, data, indent);
} else if (node instanceof XmlComment) {
serializeComment((XmlComment) node, data, indent);
} else {
// TODO throw an error ...
}
}
private static void serializeAttribute(final XmlAttribute attribute, final StringBuilder data, final int indent) {
data.append(" ");
data.append(attribute.getName());
data.append("=\"");
data.append(attribute.getValue());
data.append("\"");
}
private static void serializeAttributeList(final XmlAttributeList list, final StringBuilder data, final int indent) {
for (int iii = 0; iii < list.getAttributes().size(); iii++) {
serializeAttribute(list.getAttributes().get(iii), data, indent);
}
}
private static void serializeComment(final XmlComment comment, final StringBuilder data, final int indent) {
Tools.addIndent(data, indent);
data.append("<!--");
data.append(comment.getValue());
data.append("-->\n");
}
private static void serializeDeclaration(final XmlDeclaration declaration, final StringBuilder data, final int indent) {
Tools.addIndent(data, indent);
data.append("<?");
data.append(declaration.getValue());
serializeAttributeList(declaration, data, indent);
data.append("?>\n");
}
private static void serializeElement(final XmlElement element, final StringBuilder data, final int indent) {
Tools.addIndent(data, indent);
data.append("<");
data.append(element.getValue());
serializeAttributeList(element, data, indent);
final List<XmlNode> nodes = element.getNodes();
if (nodes.size() > 0) {
if (nodes.size() == 1 && nodes.get(0) != null && nodes.get(0).getType() == XmlNodeType.TEXT && ((XmlText) nodes.get(0)).countLines() == 1) {
data.append(">");
serialize(nodes.get(0), data, 0);
Log.verbose(" generate : '" + data + "'");
} else {
data.append(">\n");
for (int iii = 0; iii < nodes.size(); iii++) {
if (nodes.get(iii) != null) {
serialize(nodes.get(iii), data, indent + 1);
}
}
Tools.addIndent(data, indent);
}
data.append("</");
data.append(element.getValue());
data.append(">\n");
} else {
data.append("/>\n");
}
}
public static void serializeRoot(final XmlElement root, final StringBuilder data) {
for (int iii = 0; iii < root.getNodes().size(); iii++) {
final XmlNode node = root.getNodes().get(iii);
serialize(node, data, 0);
}
}
private static void serializeText(final XmlText text, final StringBuilder data, final int indent) {
data.append(Tools.replaceSpecialCharOut(text.getValue()));
}
/* CDATA generation ... maybe to add later ...
@Override
protected boolean iGenerate(final StringBuilder _data, final int _indent) {
_data.append("<![CDATA[");
_data.append(this.value);
_data.append("]]>");
return true;
}
*/
}

View File

@ -5,8 +5,9 @@
*/
package test.atriasoft.exml;
import org.atriasoft.exml.Document;
import org.atriasoft.exml.Exml;
import org.atriasoft.exml.exception.ExmlBuilderException;
import org.atriasoft.exml.model.XmlNode;
import org.junit.jupiter.api.Assertions;
class ExmlLocal {
@ -16,24 +17,25 @@ class ExmlLocal {
}
public static void test(final String _ref, final String _input, final int _errorPos, final boolean _caseInSensitive) {
final Document doc = new Document();
//doc.setCaseSensitive(!_caseInSensitive);
Log.verbose("parse : \n" + _input);
final boolean retParse = Exml.parse(_input);
if (_errorPos == 1) {
Assertions.assertEquals(retParse, false);
return;
} else {
Assertions.assertEquals(retParse, true);
XmlNode root = null;
try {
root = Exml.parse(_input);
if (_errorPos == 1) {
Assertions.fail("Must have detected an error");
return;
}
} catch (final ExmlBuilderException e) {
if (_errorPos == 1) {
return;
} else {
Assertions.fail("Must have NOT detected an error");
}
}
final StringBuilder out = new StringBuilder();
final boolean retGenerate = doc.generate(out);
if (_errorPos == 2) {
Assertions.assertEquals(retGenerate, false);
return;
} else {
Assertions.assertEquals(retGenerate, true);
}
// TODO: 2 is for failing in generate ...
Exml.generate(root, out);
final String data = out.toString();
if (_errorPos == 3) {
Assertions.assertNotEquals(_ref, data);

View File

@ -5,11 +5,10 @@
*/
package test.atriasoft.exml;
import org.atriasoft.exml.XmlAttribute;
import org.atriasoft.exml.Document;
import org.atriasoft.exml.XmlElement;
import org.atriasoft.exml.Exml;
import org.atriasoft.exml.exception.ExmlAttributeDoesNotExist;
import org.atriasoft.exml.exception.ExmlNodeDoesNotExist;
import org.atriasoft.exml.model.XmlAttribute;
import org.atriasoft.exml.model.XmlElement;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
@ -28,7 +27,6 @@ public class ExmlTestAttribute {
@Test
public void clear() {
final XmlAttribute myAttribute = new XmlAttribute("nameAttribute", "valueAttribute");
myAttribute.clear();
}
@ -51,7 +49,6 @@ public class ExmlTestAttribute {
@Test
public void exist() {
final XmlElement elem = new XmlElement("elem");
elem.setAttribute("valA", "plop");
Assertions.assertEquals(elem.existAttribute("valA"), true);
@ -60,43 +57,29 @@ public class ExmlTestAttribute {
@Test
public void get() {
final XmlElement elem = new XmlElement("elem");
elem.setAttribute("valA", "plop");
try {
Assertions.assertEquals(elem.getAttribute("valA"), "plop");
} catch (final ExmlAttributeDoesNotExist e) {
Assertions.fail("Should Not have thrown an exception");
}
final String attributeValue = Assertions.assertDoesNotThrow(() -> elem.getAttribute("valA"));
Assertions.assertEquals(attributeValue, "plop");
Assertions.assertThrows(ExmlAttributeDoesNotExist.class, () -> elem.getAttribute("qsdfsdf"));
}
@Test
public void getpair() {
final XmlElement elem = new XmlElement("elem");
elem.setAttribute("valA", "coucou");
try {
Assertions.assertEquals(elem.getAttrPair(0).first, "valA");
Assertions.assertEquals(elem.getAttrPair(0).second, "coucou");
} catch (final ExmlAttributeDoesNotExist e) {
Assertions.fail("Should Not have thrown an exception");
}
final String first = Assertions.assertDoesNotThrow(() -> elem.getAttrPair(0).first);
Assertions.assertEquals(first, "valA");
final String second = Assertions.assertDoesNotThrow(() -> elem.getAttrPair(0).second);
Assertions.assertEquals(second, "coucou");
Assertions.assertThrows(ExmlAttributeDoesNotExist.class, () -> elem.getAttrPair(1));
Assertions.assertThrows(ExmlAttributeDoesNotExist.class, () -> elem.getAttrPair(-1));
}
@Test
public void moveInAllElement() {
final Document doc = new Document();
doc.parse("<elem valA=\"plop\"/>");
XmlElement elem;
try {
elem = (XmlElement) doc.getNode("elem");
} catch (final ExmlNodeDoesNotExist e) {
Assertions.fail("Should Not have thrown an exception");
return;
}
final XmlElement root = Assertions.assertDoesNotThrow(() -> Exml.parse("<elem valA=\"plop\"/>"));
final XmlElement elem = Assertions.assertDoesNotThrow(() -> (XmlElement) root.getNode("elem"));
for (final XmlAttribute it : elem.getAttributes()) {
Assertions.assertEquals(it.getName(), "valA");
Assertions.assertEquals(it.getValue(), "plop");
@ -114,7 +97,6 @@ public class ExmlTestAttribute {
@Test
public void setGetName() {
final XmlAttribute myAttribute = new XmlAttribute("nameAttribute", "valueAttribute");
Assertions.assertEquals(myAttribute.getName(), "nameAttribute");
myAttribute.setName("newName");
@ -123,7 +105,6 @@ public class ExmlTestAttribute {
@Test
public void setGetValue() {
final XmlAttribute myAttribute = new XmlAttribute("nameAttribute", "valueAttribute");
Assertions.assertEquals(myAttribute.getValue(), "valueAttribute");
myAttribute.setValue("new value");
@ -132,31 +113,20 @@ public class ExmlTestAttribute {
@Test
public void setterNew() {
final XmlElement elem = new XmlElement("elem");
elem.setAttribute("valA", "coucou");
try {
Assertions.assertEquals(elem.getAttribute("valA"), "coucou");
} catch (final ExmlAttributeDoesNotExist e) {
Assertions.fail("Should Not have thrown an exception");
}
final String attributeValue = Assertions.assertDoesNotThrow(() -> elem.getAttribute("valA"));
Assertions.assertEquals(attributeValue, "coucou");
}
@Test
public void setterRewrite() {
final XmlElement elem = new XmlElement("elem");
elem.setAttribute("valA", "coucou");
try {
Assertions.assertEquals(elem.getAttribute("valA"), "coucou");
} catch (final ExmlAttributeDoesNotExist e) {
Assertions.fail("Should Not have thrown an exception");
}
String attributeValue = Assertions.assertDoesNotThrow(() -> elem.getAttribute("valA"));
Assertions.assertEquals(attributeValue, "coucou");
elem.setAttribute("valA", "coucou2");
try {
Assertions.assertEquals(elem.getAttribute("valA"), "coucou2");
} catch (final ExmlAttributeDoesNotExist e) {
Assertions.fail("Should Not have thrown an exception");
}
attributeValue = Assertions.assertDoesNotThrow(() -> elem.getAttribute("valA"));
Assertions.assertEquals(attributeValue, "coucou2");
}
}

View File

@ -5,9 +5,8 @@
*/
package test.atriasoft.exml;
import org.atriasoft.exml.Document;
import org.atriasoft.exml.XmlElement;
import org.atriasoft.exml.TextCDATA;
import org.atriasoft.exml.Exml;
import org.atriasoft.exml.model.XmlElement;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
@ -18,23 +17,10 @@ public class ExmlTestCData {
Log.verbose("----------------------------------------------------------------");
}
@Test
public void generate() {
final Document doc = new Document();
doc.append(new TextCDATA("Text &é<>examp]le]] ..."));
doc.append(new TextCDATA("Text &é<>examp]le]] ..."));
final String out = doc.getText();
doc.parse("<elem><![CDATA[Text &é<>examp]le]] ...]]></elem>");
Assertions.assertEquals("<![CDATA[Text &é<>examp]le]] ...]]><![CDATA[Text &é<>examp]le]] ...]]>", out);
}
@Test
public void parseCDATA() {
final Document doc = new Document();
doc.parse("<elem><![CDATA[Text &é<>examp]le]] ...]]></elem>");
final XmlElement elem = Assertions.assertDoesNotThrow(() -> {
return (XmlElement) doc.getNode("elem");
});
final XmlElement root = Assertions.assertDoesNotThrow(() -> Exml.parse("<elem><![CDATA[Text &é<>examp]le]] ...]]></elem>"));
final XmlElement elem = Assertions.assertDoesNotThrow(() -> (XmlElement) root.getNode("elem"));
Assertions.assertEquals("Text &é<>examp]le]] ...", elem.getText());
}
}

View File

@ -5,9 +5,9 @@
*/
package test.atriasoft.exml;
import org.atriasoft.exml.XmlComment;
import org.atriasoft.exml.XmlNode;
import org.atriasoft.exml.XmlNodeType;
import org.atriasoft.exml.model.XmlComment;
import org.atriasoft.exml.model.XmlNode;
import org.atriasoft.exml.model.XmlNodeType;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

View File

@ -5,9 +5,9 @@
*/
package test.atriasoft.exml;
import org.atriasoft.exml.DeclarationXML;
import org.atriasoft.exml.XmlNodeType;
import org.atriasoft.exml.exception.ExmlAttributeDoesNotExist;
import org.atriasoft.exml.model.XmlDeclaration;
import org.atriasoft.exml.model.XmlNodeType;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
@ -20,7 +20,7 @@ public class ExmlTestDeclarationXML {
@Test
public void create() {
final DeclarationXML myDeclarationXML = new DeclarationXML("1.0", "UTF-8", true);
final XmlDeclaration myDeclarationXML = new XmlDeclaration("1.0", "UTF-8", true);
Assertions.assertEquals(myDeclarationXML.getType(), XmlNodeType.DECLARATION);
try {
Assertions.assertEquals(myDeclarationXML.getAttribute("version"), "1.0");
@ -34,8 +34,8 @@ public class ExmlTestDeclarationXML {
@Test
public void createAssignement() {
final DeclarationXML myDeclarationXML = new DeclarationXML("1.0", "UTF-8", true);
final DeclarationXML myOtherDeclarationXML = myDeclarationXML.clone();
final XmlDeclaration myDeclarationXML = new XmlDeclaration("1.0", "UTF-8", true);
final XmlDeclaration myOtherDeclarationXML = myDeclarationXML.clone();
Assertions.assertEquals(myDeclarationXML.getValue(), myOtherDeclarationXML.getValue());
try {
Assertions.assertEquals(myDeclarationXML.getAttribute("version"), myOtherDeclarationXML.getAttribute("version"));
@ -48,8 +48,8 @@ public class ExmlTestDeclarationXML {
@Test
public void createCopy() {
final DeclarationXML myDeclarationXML = new DeclarationXML("1.0", "UTF-8", true);
final DeclarationXML myOtherDeclarationXML = new DeclarationXML(myDeclarationXML);
final XmlDeclaration myDeclarationXML = new XmlDeclaration("1.0", "UTF-8", true);
final XmlDeclaration myOtherDeclarationXML = new XmlDeclaration(myDeclarationXML);
Assertions.assertEquals(myDeclarationXML.getValue(), myOtherDeclarationXML.getValue());
try {
Assertions.assertEquals(myDeclarationXML.getAttribute("version"), myOtherDeclarationXML.getAttribute("version"));

View File

@ -5,11 +5,11 @@
*/
package test.atriasoft.exml;
import org.atriasoft.exml.Document;
import org.atriasoft.exml.XmlElement;
import org.atriasoft.exml.XmlNode;
import org.atriasoft.exml.XmlNodeType;
import org.atriasoft.exml.Exml;
import org.atriasoft.exml.exception.ExmlNodeDoesNotExist;
import org.atriasoft.exml.model.XmlElement;
import org.atriasoft.exml.model.XmlNode;
import org.atriasoft.exml.model.XmlNodeType;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
@ -114,9 +114,8 @@ public class ExmlTestElement {
@Test
public void moveInAllElement() {
final Document doc = new Document();
doc.parse("<elem><elem1/><elem2/></elem>");
for (final XmlNode it : doc.getNodes()) {
final XmlElement root = Assertions.assertDoesNotThrow(() -> Exml.parse("<elem><elem1/><elem2/></elem>"));
for (final XmlNode it : root.getNodes()) {
final XmlElement elem = (XmlElement) it;
Assertions.assertEquals("elem", elem.getValue());
Assertions.assertEquals(2, elem.getNodes().size());

View File

@ -29,6 +29,11 @@ public class ExmlTestParseDeclaration {
ExmlLocal.test("<?testDeclaration?>\n", "<?testDeclaration?>\n", -1);
}
@Test
public void testCaseSensitiveBalise() {
ExmlLocal.test("<Elem/>\n", "<Elem></elem>\n", -1);
}
@Test
public void testMultiline() {
ExmlLocal.test("<?xml attr=\"plop\"?>\n", "<?xml attr\n=\n\"plop\"?>\n", -1);