[DEV] start dev of a new parsing model to support sax and big file in stream
This commit is contained in:
parent
e906b9a089
commit
d16f4c95e3
@ -1,179 +0,0 @@
|
|||||||
/** @file
|
|
||||||
* @author Edouard DUPIN
|
|
||||||
* @copyright 2021, Edouard DUPIN, all right reserved
|
|
||||||
* @license MPL v2.0 (see license file)
|
|
||||||
*/
|
|
||||||
package org.atriasoft.exml;
|
|
||||||
|
|
||||||
import org.atriasoft.exml.internal.Log;
|
|
||||||
import org.atriasoft.exml.internal.PositionParsing;
|
|
||||||
import org.atriasoft.exml.internal.Tools;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Single attribute element
|
|
||||||
*/
|
|
||||||
public class Attribute {
|
|
||||||
|
|
||||||
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 ...);
|
|
||||||
protected String name; //!< Name of the attribute
|
|
||||||
|
|
||||||
public Attribute() {
|
|
||||||
this.pos = null;
|
|
||||||
this.value = "";
|
|
||||||
this.name = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
public Attribute(final Attribute _obj) {
|
|
||||||
this.pos = null;
|
|
||||||
this.value = _obj.value;
|
|
||||||
this.name = _obj.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Attribute(final String _name) {
|
|
||||||
this.name = _name;
|
|
||||||
this.value = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
* @param[in] _name Name of the attribute.
|
|
||||||
* @param[in] _value Value of the attribute.
|
|
||||||
*/
|
|
||||||
public Attribute(final String _name, final String _value) {
|
|
||||||
this.name = _name;
|
|
||||||
this.value = _value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clear() {
|
|
||||||
this.value = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Attribute clone() {
|
|
||||||
return new Attribute(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get the current name of the Attribute
|
|
||||||
* @return String of the attribute
|
|
||||||
*/
|
|
||||||
public String getName() {
|
|
||||||
return this.name;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get the current element Value.
|
|
||||||
* @return the reference of the string value.
|
|
||||||
*/
|
|
||||||
public String getValue() {
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
|
|
||||||
protected boolean iParse(final String _data, final PositionParsing _pos, final boolean _caseSensitive, final FilePos _filePos, final Document _doc) {
|
|
||||||
Log.verbose("start parse : 'attribute'");
|
|
||||||
this.pos = _filePos.clone();
|
|
||||||
// search end of the comment :
|
|
||||||
int lastElementName = _pos.value;
|
|
||||||
for (int iii = _pos.value; iii < _data.length(); iii++) {
|
|
||||||
_filePos.check(_data.charAt(iii));
|
|
||||||
Tools.drawElementParsed(_data.charAt(iii), _filePos);
|
|
||||||
if (Tools.checkAvaillable(_data.charAt(iii), false) == true) {
|
|
||||||
lastElementName = iii;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.name = _data.substring(_pos.value, lastElementName + 1);
|
|
||||||
if (_caseSensitive == true) {
|
|
||||||
this.name = this.name.toLowerCase();
|
|
||||||
}
|
|
||||||
// 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()) {
|
|
||||||
_doc.createError(_data, lastElementName + white + 1, _filePos, " parse an xml end with an attribute parsing...");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (_data.charAt(lastElementName + white + 1) != '=') {
|
|
||||||
_doc.createError(_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()) {
|
|
||||||
_doc.createError(_data, lastElementName + white + 2, _filePos, " parse an xml end with an attribute parsing...");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
boolean simpleQuoteCase = false;
|
|
||||||
if (_data.charAt(lastElementName + white + 2) == '\'') { // '
|
|
||||||
simpleQuoteCase = true;
|
|
||||||
}
|
|
||||||
if (_data.charAt(lastElementName + white + 2) != '"' && _data.charAt(lastElementName + white + 2) != '\'') { // '
|
|
||||||
// parse with no element " == > direct value separate with space ...
|
|
||||||
_filePos.increment();
|
|
||||||
int lastAttributePos = lastElementName + white + 2;
|
|
||||||
for (int iii = lastElementName + white + 2; iii < _data.length(); iii++) {
|
|
||||||
Tools.drawElementParsed(_data.charAt(iii), _filePos);
|
|
||||||
if (_filePos.check(_data.charAt(iii)) == true) {
|
|
||||||
_doc.createError(_data, iii, _filePos, "unexpected '\\n' in an attribute parsing");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (_data.charAt(iii) != ' ' && _data.charAt(iii) != '/' && _data.charAt(iii) != '?' && _data.charAt(iii) != '>') {
|
|
||||||
lastAttributePos = iii + 1;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.value = _data.substring(lastElementName + white + 2, lastAttributePos);
|
|
||||||
|
|
||||||
//EXML_PARSE_ATTRIBUTE(pos << " attribute : " << name << "=\"" << value << "\"");
|
|
||||||
|
|
||||||
_pos.value = lastAttributePos - 1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
int lastAttributePos = lastElementName + white + 3;
|
|
||||||
for (int iii = lastElementName + white + 3; iii < _data.length(); iii++) {
|
|
||||||
Tools.drawElementParsed(_data.charAt(iii), _filePos);
|
|
||||||
_filePos.check(_data.charAt(iii));
|
|
||||||
if ((_data.charAt(iii) != '"' && simpleQuoteCase == false) || (_data.charAt(iii) != '\'' && simpleQuoteCase == true)) { // '
|
|
||||||
lastAttributePos = iii + 1;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.value = _data.substring(lastElementName + white + 3, lastAttributePos);
|
|
||||||
|
|
||||||
//EXML_PARSE_ATTRIBUTE(pos << " attribute : " << name << "=\"" << value << "\"");
|
|
||||||
|
|
||||||
_pos.value = lastAttributePos;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* set the name of the attribute
|
|
||||||
* @param[in] _name New name of the attribute
|
|
||||||
*/
|
|
||||||
public void setName(final String _name) {
|
|
||||||
this.name = _name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* set the value of the node.
|
|
||||||
* @param[in] _value New value of the node.
|
|
||||||
*/
|
|
||||||
public final void setValue(final String _value) {
|
|
||||||
this.value = _value;
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,87 +0,0 @@
|
|||||||
/** @file
|
|
||||||
* @author Edouard DUPIN
|
|
||||||
* @copyright 2021, Edouard DUPIN, all right reserved
|
|
||||||
* @license MPL v2.0 (see license file)
|
|
||||||
*/
|
|
||||||
package org.atriasoft.exml;
|
|
||||||
|
|
||||||
import org.atriasoft.exml.internal.Log;
|
|
||||||
import org.atriasoft.exml.internal.PositionParsing;
|
|
||||||
import org.atriasoft.exml.internal.Tools;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Comment node: lt;!-- ... --gt;
|
|
||||||
*/
|
|
||||||
public class Comment extends Node {
|
|
||||||
|
|
||||||
public Comment() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Comment(final Comment obj) {
|
|
||||||
super(obj.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
* @param[in] _value comment value
|
|
||||||
*/
|
|
||||||
public Comment(final String _value) {
|
|
||||||
super(_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Comment clone() {
|
|
||||||
return new Comment(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NodeType getType() {
|
|
||||||
return NodeType.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;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean iParse(final String _data, final PositionParsing _pos, final boolean _caseSensitive, final FilePos _filePos, final Document _doc) {
|
|
||||||
Log.verbose("start parse : 'comment'");
|
|
||||||
this.pos = _filePos;
|
|
||||||
final FilePos tmpPos = new FilePos();
|
|
||||||
final int white = Tools.countWhiteChar(_data, _pos.value, tmpPos);
|
|
||||||
_filePos.add(tmpPos);
|
|
||||||
// search end of the comment :
|
|
||||||
for (int iii = _pos.value + white; iii + 2 < _data.length(); iii++) {
|
|
||||||
Tools.drawElementParsed(_data.charAt(iii), _filePos);
|
|
||||||
if (_filePos.check(_data.charAt(iii)) == true) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (_data.charAt(iii) == '-' && _data.charAt(iii + 1) == '-' && _data.charAt(iii + 2) == '>') {
|
|
||||||
_filePos.add(2);
|
|
||||||
// search whitespace :
|
|
||||||
int newEnd = iii;
|
|
||||||
for (int jjj = iii - 1; jjj > _pos.value; jjj--) {
|
|
||||||
if (Tools.isWhiteChar(_data.charAt(jjj)) == true) {
|
|
||||||
newEnd = jjj;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// find end of value:
|
|
||||||
this.value = _data.substring(_pos.value + white, newEnd);
|
|
||||||
Log.verbose(" find comment '" + this.value + "'");
|
|
||||||
_pos.value = iii + 2;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_pos.value = _data.length();
|
|
||||||
_doc.createError(_data, _pos.value, _filePos, "comment got end of file without finding end node");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,93 +0,0 @@
|
|||||||
/** @file
|
|
||||||
* @author Edouard DUPIN
|
|
||||||
* @copyright 2021, Edouard DUPIN, all right reserved
|
|
||||||
* @license MPL v2.0 (see license file)
|
|
||||||
*/
|
|
||||||
package org.atriasoft.exml;
|
|
||||||
|
|
||||||
import org.atriasoft.exml.internal.Log;
|
|
||||||
import org.atriasoft.exml.internal.PositionParsing;
|
|
||||||
import org.atriasoft.exml.internal.Tools;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Declaration node: lt;?XXXXXX ... gt;
|
|
||||||
*/
|
|
||||||
public class Declaration extends AttributeList {
|
|
||||||
public Declaration() {
|
|
||||||
super("");
|
|
||||||
};
|
|
||||||
|
|
||||||
public Declaration(final Declaration obj) {
|
|
||||||
super(obj.value);
|
|
||||||
for (final Attribute elem : obj.listAttribute) {
|
|
||||||
this.listAttribute.add(elem.clone());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
* @param[in] _name name of the declaration (xml, xml:xxxx ...)
|
|
||||||
*/
|
|
||||||
public Declaration(final String _name) {
|
|
||||||
super(_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Declaration clone() {
|
|
||||||
return new Declaration(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NodeType getType() {
|
|
||||||
return NodeType.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;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean iParse(final String _data, final PositionParsing _pos, final boolean _caseSensitive, final FilePos _filePos, final Document _doc) {
|
|
||||||
Log.verbose("start parse : 'declaration' : '" + this.value + "'");
|
|
||||||
this.pos = _filePos;
|
|
||||||
// search end of the comment :
|
|
||||||
for (int iii = _pos.value; iii + 1 < _data.length(); iii++) {
|
|
||||||
Tools.drawElementParsed(_data.charAt(iii), _filePos);
|
|
||||||
if (_filePos.check(_data.charAt(iii)) == true) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (_data.charAt(iii) == '>' || _data.charAt(iii) == '<') {
|
|
||||||
// an error occured :
|
|
||||||
_doc.createError(_data, _pos.value, _filePos, " find '>' or '<' instead of '?>'");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (_data.charAt(iii) == '?' && _data.charAt(iii + 1) == '>') {
|
|
||||||
_filePos.increment();
|
|
||||||
// find end of declaration:
|
|
||||||
_pos.value = iii + 1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Tools.checkAvaillable(_data.charAt(iii), true) == true) {
|
|
||||||
// we find an attibute == > create an element and parse it:
|
|
||||||
final Attribute attribute = new Attribute();
|
|
||||||
_pos.value = iii;
|
|
||||||
if (attribute.iParse(_data, _pos, _caseSensitive, _filePos, _doc) == false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
iii = _pos.value;
|
|
||||||
this.listAttribute.add(attribute);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_doc.createError(_data, _pos.value, _filePos, "Text got end of file without finding end node");
|
|
||||||
_pos.value = _data.length();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
/** @file
|
|
||||||
* @author Edouard DUPIN
|
|
||||||
* @copyright 2021, Edouard DUPIN, all right reserved
|
|
||||||
* @license MPL v2.0 (see license file)
|
|
||||||
*/
|
|
||||||
package org.atriasoft.exml;
|
|
||||||
|
|
||||||
import org.atriasoft.exml.internal.Log;
|
|
||||||
|
|
||||||
public class DeclarationXML extends Declaration {
|
|
||||||
public DeclarationXML(final DeclarationXML obj) {
|
|
||||||
super(obj.value);
|
|
||||||
for (final Attribute elem : obj.listAttribute) {
|
|
||||||
this.listAttribute.add(elem.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public DeclarationXML(final String _version, final String _format, final boolean _standalone) {
|
|
||||||
super("xml");
|
|
||||||
if (_version.isEmpty() != true) {
|
|
||||||
setAttribute("version", _version);
|
|
||||||
}
|
|
||||||
if (_format.contentEquals("UTF-8")) {
|
|
||||||
setAttribute("encoding", "UTF-8");
|
|
||||||
} else {
|
|
||||||
Log.error("Actually does not supported other charset than UTF8");
|
|
||||||
setAttribute("encoding", "UTF-8");
|
|
||||||
}
|
|
||||||
if (_standalone == true) {
|
|
||||||
setAttribute("standalone", "true");
|
|
||||||
} else {
|
|
||||||
setAttribute("standalone", "true");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DeclarationXML clone() {
|
|
||||||
return new DeclarationXML(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,243 +0,0 @@
|
|||||||
/** @file
|
|
||||||
* @author Edouard DUPIN
|
|
||||||
* @copyright 2021, Edouard DUPIN, all right reserved
|
|
||||||
* @license MPL v2.0 (see license file)
|
|
||||||
*/
|
|
||||||
package org.atriasoft.exml;
|
|
||||||
|
|
||||||
import org.atriasoft.exml.internal.Log;
|
|
||||||
import org.atriasoft.exml.internal.PositionParsing;
|
|
||||||
import org.atriasoft.exml.internal.Tools;
|
|
||||||
|
|
||||||
/** @file
|
|
||||||
* @author Edouard DUPIN
|
|
||||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
|
||||||
* @license MPL v2.0 (see license file)
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* Basic document element of a document
|
|
||||||
*/
|
|
||||||
public class Document extends Element {
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
public Document() {
|
|
||||||
this.caseSensitive = false;
|
|
||||||
this.writeErrorWhenDetexted = true;
|
|
||||||
this.comment = "";
|
|
||||||
this.Line = "";
|
|
||||||
this.filePos = new FilePos(0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clear() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
public void createError(final String _data, final int _pos, final FilePos _filePos, final String _comment) {
|
|
||||||
this.comment = _comment;
|
|
||||||
this.Line = extract_line(_data, _pos);
|
|
||||||
this.filePos = _filePos;
|
|
||||||
if (this.writeErrorWhenDetexted == true) {
|
|
||||||
displayError();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Display the Document on console
|
|
||||||
*/
|
|
||||||
public void display() {
|
|
||||||
final StringBuilder tmpp = new StringBuilder();
|
|
||||||
iGenerate(tmpp, 0);
|
|
||||||
Log.info("Generated XML : \n" + tmpp.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Request display in log of the error
|
|
||||||
*/
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
String extract_line(final String data, final int _pos) {
|
|
||||||
// search back : '\n'
|
|
||||||
int startPos = data.lastIndexOf('\n', _pos);
|
|
||||||
if (startPos == _pos) {
|
|
||||||
startPos = 0;
|
|
||||||
} else {
|
|
||||||
startPos++;
|
|
||||||
}
|
|
||||||
// search forward : '\n'
|
|
||||||
int stopPos = _pos;
|
|
||||||
if (data.length() == _pos) {
|
|
||||||
stopPos = _pos;
|
|
||||||
} else if (data.charAt(_pos) != '\n') {
|
|
||||||
stopPos = data.indexOf('\n', _pos);
|
|
||||||
if (stopPos == _pos) {
|
|
||||||
stopPos = data.length();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (startPos == -1) {
|
|
||||||
startPos = 0;
|
|
||||||
} else if (startPos >= data.length()) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
if (stopPos == -1) {
|
|
||||||
return "";
|
|
||||||
} else if (stopPos >= data.length()) {
|
|
||||||
stopPos = data.length();
|
|
||||||
}
|
|
||||||
return data.substring(startPos, stopPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* generate a string that contain the created XML
|
|
||||||
* @param[out] _data Data where the xml is stored
|
|
||||||
* @return false : An error occured
|
|
||||||
* @return true : Parsing is OK
|
|
||||||
*/
|
|
||||||
public boolean generate(final StringBuilder _data) {
|
|
||||||
return iGenerate(_data, 0);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Load the file that might contain the xml
|
|
||||||
* @param[in] _uri URI of the xml
|
|
||||||
* @return false : An error occured
|
|
||||||
* @return true : Parsing is OK
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
public boolean load( Uri _uri){
|
|
||||||
// Start loading the XML :
|
|
||||||
EXML_VERBOSE("open file (xml) " + _uri);
|
|
||||||
clear();
|
|
||||||
auto fileIo = uri::get(_uri);
|
|
||||||
if (fileIo == null) {
|
|
||||||
Log.error("File Does not exist : " + _uri);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (fileIo->open(io::OpenMode::Read) == false) {
|
|
||||||
Log.error("Can not open (r) the file : " + _uri);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// load data from the file:
|
|
||||||
String tmpDataUnicode = fileIo->readAllString();
|
|
||||||
// close the file:
|
|
||||||
fileIo->close();
|
|
||||||
// parse the data:
|
|
||||||
boolean ret = parse(tmpDataUnicode);
|
|
||||||
//Display();
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* Store the Xml in the file
|
|
||||||
* @param[in] _uri URI of the xml
|
|
||||||
* @return false : An error occured
|
|
||||||
* @return true : Parsing is OK
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
public boolean store( Uri _uri){
|
|
||||||
String createData;
|
|
||||||
if (generate(createData) == false) {
|
|
||||||
Log.error("Error while creating the XML: " + _uri);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
auto fileIo = uri::get(_uri);
|
|
||||||
if (fileIo == null) {
|
|
||||||
Log.error("Can not create the uri: " + _uri);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (fileIo->open(io::OpenMode::Write) == false) {
|
|
||||||
Log.error("Can not open (r) the file : " + _uri);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
fileIo->writeAll(createData);
|
|
||||||
fileIo->close();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* get the status of case sensitive mode.
|
|
||||||
* @return true if case sensitive is active
|
|
||||||
*/
|
|
||||||
public boolean getCaseSensitive() {
|
|
||||||
return this.caseSensitive;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the display of the error status.
|
|
||||||
* @return true Display error
|
|
||||||
* @return false Does not display error (get it at end)
|
|
||||||
*/
|
|
||||||
public boolean getDisplayError() {
|
|
||||||
return this.writeErrorWhenDetexted;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NodeType getType() {
|
|
||||||
return NodeType.DOCUMENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* parse a string that contain an XML
|
|
||||||
* @param[in] _data Data to parse
|
|
||||||
* @return false : An error occured
|
|
||||||
* @return true : Parsing is OK
|
|
||||||
*/
|
|
||||||
public boolean parse(final String _data) {
|
|
||||||
Log.verbose("Start parsing document (type: string) size=" + _data.length());
|
|
||||||
clear();
|
|
||||||
// came from char == > force in utf8 ...
|
|
||||||
this.pos = new FilePos(1, 0);
|
|
||||||
final PositionParsing parsePos = new PositionParsing();
|
|
||||||
return subParse(_data, parsePos, this.caseSensitive, this.pos, this, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the display of the error when detected.
|
|
||||||
* @param[in] _value true: display error, false not display error (get it at end)
|
|
||||||
*/
|
|
||||||
public void setDisplayError(final boolean _value) {
|
|
||||||
this.writeErrorWhenDetexted = _value;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,536 +0,0 @@
|
|||||||
/** @file
|
|
||||||
* @author Edouard DUPIN
|
|
||||||
* @copyright 2021, Edouard DUPIN, all right reserved
|
|
||||||
* @license MPL v2.0 (see license file)
|
|
||||||
*/
|
|
||||||
package org.atriasoft.exml;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
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.PositionParsing;
|
|
||||||
import org.atriasoft.exml.internal.Tools;
|
|
||||||
|
|
||||||
/** @file
|
|
||||||
* @author Edouard DUPIN
|
|
||||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
|
||||||
* @license MPL v2.0 (see license file)
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* Basic element Node of an XML document lt;YYYYYgt;
|
|
||||||
*/
|
|
||||||
public class Element extends AttributeList {
|
|
||||||
protected List<Node> listSub = new ArrayList<>(); //!< List of subNodes;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
public Element() {
|
|
||||||
super();
|
|
||||||
};
|
|
||||||
|
|
||||||
public Element(final Element obj) throws CloneNotSupportedException {
|
|
||||||
super(obj.value);
|
|
||||||
for (final Attribute elem : obj.listAttribute) {
|
|
||||||
this.listAttribute.add(elem.clone());
|
|
||||||
}
|
|
||||||
for (final Node elem : obj.listSub) {
|
|
||||||
this.listSub.add(elem.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
* @param[in] _value Element name;
|
|
||||||
*/
|
|
||||||
public Element(final String _value) {
|
|
||||||
super(_value);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* add a node at the element (not Attribute (move in the attribute automaticly).
|
|
||||||
* @param[in] _node Pointer of the node to add.
|
|
||||||
*/
|
|
||||||
public void append(final Node _node) {
|
|
||||||
if (_node == null) {
|
|
||||||
Log.error("Try to set an empty node");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (int iii = 0; iii < this.listSub.size(); iii++) {
|
|
||||||
if (this.listSub.get(iii) == _node) {
|
|
||||||
Log.error("Try to add a node that is already added before !!!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.listSub.add(_node);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clear() {
|
|
||||||
super.clear();
|
|
||||||
this.listSub.clear();
|
|
||||||
};
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Element clone() throws CloneNotSupportedException {
|
|
||||||
return new Element(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get the Node pointer of the element id.
|
|
||||||
* @param[in] _id Id of the element.
|
|
||||||
* @return true if the Node exist.
|
|
||||||
*/
|
|
||||||
public boolean existNode(final int _id) {
|
|
||||||
if (_id < 0 || _id >= this.listSub.size()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get an element with his name (work only with Element)
|
|
||||||
* @param[in] _name Name of the element that is requested
|
|
||||||
* @return true if the Node exist.
|
|
||||||
*/
|
|
||||||
public boolean existNode(final String _name) {
|
|
||||||
if (_name.isEmpty() == true) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (int iii = 0; iii < this.listSub.size(); iii++) {
|
|
||||||
if (this.listSub.get(iii) != null && this.listSub.get(iii).getValue().contentEquals(_name) == true) {
|
|
||||||
if (this.listSub.get(iii) == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get the Node pointer of the element id.
|
|
||||||
* @param[in] _id Id of the element.
|
|
||||||
* @return Pointer on node.
|
|
||||||
* @throws ExmlNodeDoesNotExist The Node does not exist
|
|
||||||
*/
|
|
||||||
public Node getNode(final int _id) throws ExmlNodeDoesNotExist {
|
|
||||||
if (_id < 0 || _id >= this.listSub.size()) {
|
|
||||||
throw new ExmlNodeDoesNotExist("Node does not exist: " + _id + "/" + this.listSub.size());
|
|
||||||
}
|
|
||||||
return this.listSub.get(_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get an element with his name (work only with Element)
|
|
||||||
* @param[in] _name Name of the element that is requested
|
|
||||||
* @return Pointer on the node.
|
|
||||||
* @throws ExmlNodeDoesNotExist The Node does not exist
|
|
||||||
*/
|
|
||||||
public Node getNode(final String _name) throws ExmlNodeDoesNotExist {
|
|
||||||
if (_name.isEmpty() == true) {
|
|
||||||
throw new ExmlNodeDoesNotExist("Node can not have empty name in " + this.listAttribute.size() + " nodes");
|
|
||||||
}
|
|
||||||
for (int iii = 0; iii < this.listSub.size(); iii++) {
|
|
||||||
if (this.listSub.get(iii) != null && this.listSub.get(iii).getValue().contentEquals(_name) == true) {
|
|
||||||
return this.listSub.get(iii);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new ExmlNodeDoesNotExist("Node does not exist: '" + _name + "' in " + this.listAttribute.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the list of the sub-nodes.
|
|
||||||
* @return List of current nodes.
|
|
||||||
*/
|
|
||||||
public List<Node> getNodes() {
|
|
||||||
return 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...
|
|
||||||
*/
|
|
||||||
public String getText() {
|
|
||||||
final StringBuilder res = new StringBuilder();
|
|
||||||
if (this.listSub.size() == 1) {
|
|
||||||
if (this.listSub.get(0).getType() == NodeType.TEXT) {
|
|
||||||
res.append(this.listSub.get(0).getValue());
|
|
||||||
} else {
|
|
||||||
this.listSub.get(0).iGenerate(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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NodeType getType() {
|
|
||||||
return NodeType.ELEMENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get the type of the element id.
|
|
||||||
* @param[in] _id Id of the element.
|
|
||||||
* @return the Current type of the element or typeUnknow.
|
|
||||||
* @throws ExmlNodeDoesNotExist The Node does not exist
|
|
||||||
*/
|
|
||||||
public NodeType getType(final int _id) throws ExmlNodeDoesNotExist {
|
|
||||||
if (_id < 0 || _id >= this.listSub.size()) {
|
|
||||||
throw new ExmlNodeDoesNotExist("Node does not exist: " + _id + "/" + this.listSub.size());
|
|
||||||
}
|
|
||||||
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() == NodeType.TEXT && ((Text) 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean iParse(final String _data, final PositionParsing _pos, final boolean _caseSensitive, final FilePos _filePos, final Document _doc) {
|
|
||||||
//EXML_PARSE_ELEMENT("start parse : 'element' named='" + value + "'");
|
|
||||||
// note : When start parsing the upper element must have set the value of the element and set the position after this one
|
|
||||||
this.pos = _filePos.clone();
|
|
||||||
// find a normal node ...
|
|
||||||
for (int iii = _pos.value; iii < _data.length(); iii++) {
|
|
||||||
_filePos.check(_data.charAt(iii));
|
|
||||||
Tools.drawElementParsed(_data.charAt(iii), _filePos);
|
|
||||||
if (_data.charAt(iii) == '>') {
|
|
||||||
// we find the end ...
|
|
||||||
_pos.value = iii + 1;
|
|
||||||
return subParse(_data, _pos, _caseSensitive, _filePos, _doc, false);
|
|
||||||
}
|
|
||||||
if (_data.charAt(iii) == '/') {
|
|
||||||
// standalone node or error...
|
|
||||||
if (iii + 1 >= _data.length()) {
|
|
||||||
_doc.createError(_data, _pos.value, _filePos, "Find end of files ... == > bad case");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// TODO : Can have white spaces ....
|
|
||||||
if (_data.charAt(iii + 1) == '>') {
|
|
||||||
_pos.value = iii + 1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// error
|
|
||||||
_doc.createError(_data, _pos.value, _filePos, "Find / without > char ...");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (Tools.checkAvaillable(_data.charAt(iii), true) == true) {
|
|
||||||
// we find an attibute == > create an element and parse it:
|
|
||||||
final Attribute attribute = new Attribute();
|
|
||||||
_pos.value = iii;
|
|
||||||
if (attribute.iParse(_data, _pos, _caseSensitive, _filePos, _doc) == false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
iii = _pos.value;
|
|
||||||
this.listAttribute.add(attribute);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (Tools.isWhiteChar(_data.charAt(iii)) == false) {
|
|
||||||
_doc.createError(_data, iii, _filePos, "Find an unknow element : '" + _data.charAt(iii) + "'");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_doc.createError(_data, _pos.value, _filePos, "Unexpecting end of parsing exml::internal::Element : '" + this.value + "' == > check if the '/>' is set or the end of element");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove all element with this name
|
|
||||||
* @param[in] _nodeName Name of nodes to remove.
|
|
||||||
*/
|
|
||||||
public void remove(final String _nodeName) {
|
|
||||||
if (_nodeName == "") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (final ListIterator<Node> iter = this.listSub.listIterator(); iter.hasNext();) {
|
|
||||||
final Node element = iter.next();
|
|
||||||
if (element == null) {
|
|
||||||
iter.remove();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (element.getValue().contentEquals(_nodeName) == true) {
|
|
||||||
iter.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get the number of sub element in the node (can be Comment ; Element ; Text :Declaration).
|
|
||||||
* @return a number >=0.
|
|
||||||
*/
|
|
||||||
public int size() {
|
|
||||||
return this.listSub.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse sub node string
|
|
||||||
* @param[in] _data all file string data
|
|
||||||
* @param[in,out] _pos Position to start parsing in the file and return the end of parsing
|
|
||||||
* @param[in] _caseSensitive Case sensitive parsing (usefull for html)
|
|
||||||
* @param[in] _filePos Current File position of the parsing
|
|
||||||
* @param[in] _doc Document base reference
|
|
||||||
* @param[in] _mainNode if true, this is the first root node
|
|
||||||
* @return true parsing is done OK
|
|
||||||
* @return false An error appear in the parsing
|
|
||||||
*/
|
|
||||||
protected boolean subParse(final String _data, final PositionParsing _pos, final boolean _caseSensitive, final FilePos _filePos, final Document _doc) {
|
|
||||||
return subParse(_data, _pos, _caseSensitive, _filePos, _doc, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean subParse(final String _data, final PositionParsing _pos, final boolean _caseSensitive, final FilePos _filePos, final Document _doc, final boolean _mainNode) {
|
|
||||||
//EXML_PARSE_ELEMENT(" start subParse ... " << _pos << " " << _filePos);
|
|
||||||
for (int iii = _pos.value; iii < _data.length(); iii++) {
|
|
||||||
_filePos.check(_data.charAt(iii));
|
|
||||||
Tools.drawElementParsed(_data.charAt(iii), _filePos);
|
|
||||||
final FilePos tmpPos = new FilePos();
|
|
||||||
if (_data.charAt(iii) == '<') {
|
|
||||||
final int white = Tools.countWhiteChar(_data, iii + 1, tmpPos);
|
|
||||||
if (iii + white + 1 >= _data.length()) {
|
|
||||||
_filePos.add(tmpPos);
|
|
||||||
_doc.createError(_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);
|
|
||||||
_doc.createError(_data, _pos.value, _filePos, "Find '>' with no element in the element...");
|
|
||||||
_pos.value = iii + white + 1;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (_data.charAt(iii + white + 1) == '?') {
|
|
||||||
tmpPos.increment();
|
|
||||||
// TODO : white space ...
|
|
||||||
if (Tools.checkAvaillable(_data.charAt(iii + white + 2), true) == false) {
|
|
||||||
_doc.createError(_data, _pos.value, _filePos, "Find unavaillable name in the Declaration node...");
|
|
||||||
_pos.value = iii + white + 1;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
//EXML_DEBUG("Generate node name : '" << _data[iii+1] << "'");
|
|
||||||
int endPosName = iii + white + 1;
|
|
||||||
// generate element name ...
|
|
||||||
for (int jjj = iii + white + 2; jjj < _data.length(); jjj++) {
|
|
||||||
if (Tools.checkAvaillable(_data.charAt(jjj), false) == true) {
|
|
||||||
// we find the end ...
|
|
||||||
endPosName = jjj;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
tmpPos.check(_data.charAt(jjj));
|
|
||||||
}
|
|
||||||
String tmpname = _data.substring(iii + white + 2, endPosName + 1);
|
|
||||||
if (_caseSensitive == true) {
|
|
||||||
tmpname = tmpname.toLowerCase();
|
|
||||||
}
|
|
||||||
// Find declaration marker
|
|
||||||
final Declaration declaration = new Declaration(tmpname);
|
|
||||||
_filePos.add(tmpPos);
|
|
||||||
_pos.value = endPosName + 1;
|
|
||||||
if (declaration.iParse(_data, _pos, _caseSensitive, _filePos, _doc) == false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
iii = _pos.value;
|
|
||||||
this.listSub.add(declaration);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (_data.charAt(iii + white + 1) == '!') {
|
|
||||||
tmpPos.increment();
|
|
||||||
// Find special block element
|
|
||||||
if (iii + white + 2 >= _data.length()) {
|
|
||||||
_doc.createError(_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()) {
|
|
||||||
_doc.createError(_data, _pos.value, _filePos, "End file with '<!-' chars == > invalide XML");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (_data.charAt(iii + white + 3) != '-') {
|
|
||||||
_doc.createError(_data, _pos.value, _filePos, "Element parse with '<!-" + _data.charAt(iii + 3) + "' chars == > invalide XML");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
tmpPos.increment();
|
|
||||||
// find comment:
|
|
||||||
final Comment comment = new Comment();
|
|
||||||
_pos.value = iii + white + 4;
|
|
||||||
_filePos.add(tmpPos);
|
|
||||||
if (comment.iParse(_data, _pos, _caseSensitive, _filePos, _doc) == false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
iii = _pos.value;
|
|
||||||
this.listSub.add(comment);
|
|
||||||
} else if (_data.charAt(iii + white + 2) == '[') {
|
|
||||||
tmpPos.increment();
|
|
||||||
if (iii + white + 8 >= _data.length()) {
|
|
||||||
_doc.createError(_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) != '[') {
|
|
||||||
_doc.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");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
tmpPos.add(6);
|
|
||||||
// find text:
|
|
||||||
final TextCDATA text = new TextCDATA();
|
|
||||||
_pos.value = iii + 9 + white;
|
|
||||||
_filePos.add(tmpPos);
|
|
||||||
if (text.iParse(_data, _pos, _caseSensitive, _filePos, _doc) == false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
iii = _pos.value;
|
|
||||||
this.listSub.add(text);
|
|
||||||
} else {
|
|
||||||
_doc.createError(_data, _pos.value, _filePos, "End file with '<!" + _data.charAt(iii + white + 2) + "' chars == > invalide XML");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (_data.charAt(iii + white + 1) == '/') {
|
|
||||||
tmpPos.increment();
|
|
||||||
//EXML_DEBUG("Generate node name : '" << _data[iii+1] << "'");
|
|
||||||
int endPosName = iii + white + 1;
|
|
||||||
// generate element name ...
|
|
||||||
for (int jjj = iii + white + 2; jjj < _data.length(); jjj++) {
|
|
||||||
if (Tools.checkAvaillable(_data.charAt(jjj), false) == true) {
|
|
||||||
// we find the end ...
|
|
||||||
endPosName = jjj;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
tmpPos.check(_data.charAt(jjj));
|
|
||||||
}
|
|
||||||
String tmpname = _data.substring(iii + white + 2, endPosName + 1);
|
|
||||||
if (_caseSensitive == true) {
|
|
||||||
tmpname = tmpname.toLowerCase();
|
|
||||||
}
|
|
||||||
if (tmpname.contentEquals(this.value) == true) {
|
|
||||||
// find end of node :
|
|
||||||
// find > element ...
|
|
||||||
for (int jjj = endPosName + 1; jjj < _data.length(); jjj++) {
|
|
||||||
Tools.drawElementParsed(_data.charAt(jjj), _filePos);
|
|
||||||
if (tmpPos.check(_data.charAt(jjj)) == true) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (_data.charAt(jjj) == '>') {
|
|
||||||
_pos.value = jjj;
|
|
||||||
_filePos.add(tmpPos);
|
|
||||||
return true;
|
|
||||||
} else if (_data.charAt(jjj) != '\r' && _data.charAt(jjj) != ' ' && _data.charAt(jjj) != '\t') {
|
|
||||||
_filePos.add(tmpPos);
|
|
||||||
_doc.createError(_data, jjj, _filePos, "End node error : have data inside end node other than [ \\n\\t\\r] " + this.value + "'");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
_doc.createError(_data, _pos.value, _filePos, "End node error : '" + tmpname + "' != '" + this.value + "'");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (_data.charAt(iii + white + 1) == '>') {
|
|
||||||
// end of something == > this is really bad
|
|
||||||
_doc.createError(_data, _pos.value, _filePos, "Find '>' chars == > invalide XML");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Tools.checkAvaillable(_data.charAt(iii + white + 1), true) == true) {
|
|
||||||
tmpPos.increment();
|
|
||||||
Log.debug("Generate node name : '" + _data.charAt(iii + 1) + "'");
|
|
||||||
int endPosName = iii + white + 1;
|
|
||||||
// generate element name ...
|
|
||||||
for (int jjj = iii + white + 2; jjj < _data.length(); jjj++) {
|
|
||||||
if (Tools.checkAvaillable(_data.charAt(jjj), false) == true) {
|
|
||||||
// we find the end ...
|
|
||||||
endPosName = jjj;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
tmpPos.check(_data.charAt(jjj));
|
|
||||||
}
|
|
||||||
String tmpname = _data.substring(iii + white + 1, endPosName + 1);
|
|
||||||
if (_caseSensitive == true) {
|
|
||||||
tmpname = tmpname.toLowerCase();
|
|
||||||
}
|
|
||||||
Log.debug("find node named : '" + tmpname + "'");
|
|
||||||
// find text:
|
|
||||||
final Element element = new Element(tmpname);
|
|
||||||
_pos.value = endPosName + 1;
|
|
||||||
_filePos.add(tmpPos);
|
|
||||||
if (element.iParse(_data, _pos, _caseSensitive, _filePos, _doc) == false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
iii = _pos.value;
|
|
||||||
this.listSub.add(element);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
_filePos.add(tmpPos);
|
|
||||||
// here we have an error :
|
|
||||||
_doc.createError(_data, _pos.value, _filePos, "Find an ununderstanding element : '" + _data.charAt(iii + white + 1) + "'");
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
if (_data.charAt(iii) == '>') {
|
|
||||||
_doc.createError(_data, _pos.value, _filePos, "Find elemement '>' == > no reason to be here ...");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// might to be data text ...
|
|
||||||
if (_data.charAt(iii) == '\n' || _data.charAt(iii) == ' ' || _data.charAt(iii) == '\t' || _data.charAt(iii) == '\r') {
|
|
||||||
// empty spaces == > nothing to do ....
|
|
||||||
} else {
|
|
||||||
// find data == > parse it...
|
|
||||||
final Text text = new Text();
|
|
||||||
_pos.value = iii;
|
|
||||||
_filePos.add(tmpPos);
|
|
||||||
if (text.iParse(_data, _pos, _caseSensitive, _filePos, _doc) == false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
iii = _pos.value;
|
|
||||||
this.listSub.add(text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (_mainNode == true) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
_doc.createError(_data, _pos.value, _filePos, "Did not find end of the exml::internal::Element : '" + this.value + "'");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
121
src/org/atriasoft/exml/Exml.java
Normal file
121
src/org/atriasoft/exml/Exml.java
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
/** @file
|
||||||
|
* @author Edouard DUPIN
|
||||||
|
* @copyright 2021, Edouard DUPIN, all right reserved
|
||||||
|
* @license MPL v2.0 (see license file)
|
||||||
|
*/
|
||||||
|
|
||||||
|
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.internal.Log;
|
||||||
|
import org.atriasoft.exml.parser.ParseXml;
|
||||||
|
|
||||||
|
public class Exml {
|
||||||
|
/**
|
||||||
|
* Display the Document on console
|
||||||
|
*/
|
||||||
|
public static void display() {
|
||||||
|
final StringBuilder tmpp = new StringBuilder();
|
||||||
|
//iGenerate(tmpp, 0);
|
||||||
|
Log.info("Generated XML : \n" + tmpp.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* generate a string that contain the created XML
|
||||||
|
* @param[out] _data Data where the xml is stored
|
||||||
|
* @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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static XmlNode parse(final String data) {
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load the file that might contain the xml
|
||||||
|
* @param[in] _uri URI of the xml
|
||||||
|
* @return false : An error occured
|
||||||
|
* @return true : Parsing is OK
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
public boolean load( Uri _uri){
|
||||||
|
// Start loading the XML :
|
||||||
|
EXML_VERBOSE("open file (xml) " + _uri);
|
||||||
|
clear();
|
||||||
|
auto fileIo = uri::get(_uri);
|
||||||
|
if (fileIo == null) {
|
||||||
|
Log.error("File Does not exist : " + _uri);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (fileIo->open(io::OpenMode::Read) == false) {
|
||||||
|
Log.error("Can not open (r) the file : " + _uri);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// load data from the file:
|
||||||
|
String tmpDataUnicode = fileIo->readAllString();
|
||||||
|
// close the file:
|
||||||
|
fileIo->close();
|
||||||
|
// parse the data:
|
||||||
|
boolean ret = parse(tmpDataUnicode);
|
||||||
|
//Display();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Store the Xml in the file
|
||||||
|
* @param[in] _uri URI of the xml
|
||||||
|
* @return false : An error occured
|
||||||
|
* @return true : Parsing is OK
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
public boolean store( Uri _uri){
|
||||||
|
String createData;
|
||||||
|
if (generate(createData) == false) {
|
||||||
|
Log.error("Error while creating the XML: " + _uri);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto fileIo = uri::get(_uri);
|
||||||
|
if (fileIo == null) {
|
||||||
|
Log.error("Can not create the uri: " + _uri);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (fileIo->open(io::OpenMode::Write) == false) {
|
||||||
|
Log.error("Can not open (r) the file : " + _uri);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
fileIo->writeAll(createData);
|
||||||
|
fileIo->close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
private Exml() {}
|
||||||
|
}
|
@ -1,116 +0,0 @@
|
|||||||
/** @file
|
|
||||||
* @author Edouard DUPIN
|
|
||||||
* @copyright 2021, Edouard DUPIN, all right reserved
|
|
||||||
* @license MPL v2.0 (see license file)
|
|
||||||
*/
|
|
||||||
package org.atriasoft.exml;
|
|
||||||
|
|
||||||
import org.atriasoft.exml.internal.Log;
|
|
||||||
import org.atriasoft.exml.internal.PositionParsing;
|
|
||||||
import org.atriasoft.exml.internal.Tools;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Text node interface (internal data between two Marker: <XXX> ALL here </XXX>
|
|
||||||
*/
|
|
||||||
public class Text extends Node {
|
|
||||||
|
|
||||||
// transform the Text with :
|
|
||||||
// "<" == "<"
|
|
||||||
// ">" == ">"
|
|
||||||
// "&" == "&"
|
|
||||||
// "'" == "'"
|
|
||||||
// """ == """
|
|
||||||
private static String replaceSpecialChar(final String _inval) {
|
|
||||||
final String out = _inval;
|
|
||||||
out.replace("<", "<");
|
|
||||||
out.replace(">", ">");
|
|
||||||
out.replace("'", "'");
|
|
||||||
out.replace(""", "\"");
|
|
||||||
out.replace("&", "&");
|
|
||||||
//EXML_ERROR("INNN '"<< _inval << "' => '" << out << "'");
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String replaceSpecialCharOut(final String _inval) {
|
|
||||||
final String out = _inval;
|
|
||||||
out.replace("<", "<");
|
|
||||||
out.replace(">", ">");
|
|
||||||
out.replace("'", "'");
|
|
||||||
out.replace("\"", """);
|
|
||||||
out.replace("&", "&");
|
|
||||||
//EXML_ERROR("OUTTT '"<< _inval << "' => '" << out << "'");
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
public Text() {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
* @param[in] _data String data of the current Text
|
|
||||||
*/
|
|
||||||
public Text(final String _data) {
|
|
||||||
super(_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* count the number of line in the current text
|
|
||||||
* @return The number of lines
|
|
||||||
*/
|
|
||||||
protected int countLines() {
|
|
||||||
int count = 1;
|
|
||||||
for (int iii = 0; iii < this.value.length(); iii++) {
|
|
||||||
if (this.value.charAt(iii) == '\n') {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NodeType getType() {
|
|
||||||
return NodeType.TEXT;
|
|
||||||
};
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean iGenerate(final StringBuilder _data, final int _indent) {
|
|
||||||
_data.append(replaceSpecialCharOut(this.value));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean iParse(final String _data, final PositionParsing _pos, final boolean _caseSensitive, final FilePos _filePos, final Document _doc) {
|
|
||||||
Log.verbose("start parse : 'text'");
|
|
||||||
this.pos = _filePos.clone();
|
|
||||||
// search end of the comment :
|
|
||||||
for (int iii = _pos.value; iii < _data.length(); iii++) {
|
|
||||||
Tools.drawElementParsed(_data.charAt(iii), _filePos);
|
|
||||||
if (_filePos.check(_data.charAt(iii)) == true) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (_data.charAt(iii) == '>' || _data.charAt(iii) == '<') {
|
|
||||||
// search whitespace :
|
|
||||||
int newEnd = iii;
|
|
||||||
for (int jjj = iii - 1; jjj > _pos.value; --jjj) {
|
|
||||||
if (Tools.isWhiteChar(_data.charAt(jjj)) == true) {
|
|
||||||
newEnd = jjj;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// find end of value:
|
|
||||||
this.value = _data.substring(_pos.value, newEnd);
|
|
||||||
Log.verbose(" find text '" + this.value + "'");
|
|
||||||
_pos.value = iii - 1;
|
|
||||||
this.value = replaceSpecialChar(this.value);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_doc.createError(_data, _pos.value, _filePos, "Text got end of file without finding end node");
|
|
||||||
_pos.value = _data.length();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
@ -5,11 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.atriasoft.exml;
|
package org.atriasoft.exml;
|
||||||
|
|
||||||
import org.atriasoft.exml.internal.Log;
|
public class TextCDATA extends XmlText {
|
||||||
import org.atriasoft.exml.internal.PositionParsing;
|
|
||||||
import org.atriasoft.exml.internal.Tools;
|
|
||||||
|
|
||||||
public class TextCDATA extends Text {
|
|
||||||
public TextCDATA() {
|
public TextCDATA() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
@ -26,27 +22,4 @@ public class TextCDATA extends Text {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean iParse(final String _data, final PositionParsing _pos, final boolean _caseSensitive, final FilePos _filePos, final Document _doc) {
|
|
||||||
Log.verbose("start parse : 'text::CDATA'");
|
|
||||||
this.pos = _filePos.clone();
|
|
||||||
// search end of the comment :
|
|
||||||
for (int iii = _pos.value; iii + 2 < _data.length(); iii++) {
|
|
||||||
Tools.drawElementParsed(_data.charAt(iii), _filePos);
|
|
||||||
if (_filePos.check(_data.charAt(iii)) == true) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (_data.charAt(iii) == ']' && _data.charAt(iii + 1) == ']' && _data.charAt(iii + 2) == '>') {
|
|
||||||
// find end of value:
|
|
||||||
_filePos.add(2);
|
|
||||||
this.value = _data.substring(_pos.value, iii);
|
|
||||||
Log.verbose(" find text CDATA '" + this.value + "'");
|
|
||||||
_pos.value = iii + 2;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_doc.createError(_data, _pos.value, _filePos, "text CDATA got end of file without finding end node");
|
|
||||||
_pos.value = _data.length();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
95
src/org/atriasoft/exml/XmlAttribute.java
Normal file
95
src/org/atriasoft/exml/XmlAttribute.java
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
/** @file
|
||||||
|
* @author Edouard DUPIN
|
||||||
|
* @copyright 2021, Edouard DUPIN, all right reserved
|
||||||
|
* @license MPL v2.0 (see license file)
|
||||||
|
*/
|
||||||
|
package org.atriasoft.exml;
|
||||||
|
|
||||||
|
import org.atriasoft.exml.internal.FilePos;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Single attribute element
|
||||||
|
*/
|
||||||
|
public class XmlAttribute {
|
||||||
|
|
||||||
|
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 ...);
|
||||||
|
protected String name; //!< Name of the attribute
|
||||||
|
|
||||||
|
public XmlAttribute() {
|
||||||
|
this.pos = null;
|
||||||
|
this.value = "";
|
||||||
|
this.name = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public XmlAttribute(final String _name) {
|
||||||
|
this.name = _name;
|
||||||
|
this.value = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param[in] _name Name of the attribute.
|
||||||
|
* @param[in] _value Value of the attribute.
|
||||||
|
*/
|
||||||
|
public XmlAttribute(final String _name, final String _value) {
|
||||||
|
this.name = _name;
|
||||||
|
this.value = _value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public XmlAttribute(final XmlAttribute _obj) {
|
||||||
|
this.pos = null;
|
||||||
|
this.value = _obj.value;
|
||||||
|
this.name = _obj.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
this.value = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlAttribute clone() {
|
||||||
|
return new XmlAttribute(this.name, this.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the current name of the Attribute
|
||||||
|
* @return String of the attribute
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return this.name;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the current element Value.
|
||||||
|
* @return the reference of the string value.
|
||||||
|
*/
|
||||||
|
public String getValue() {
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
public void setName(final String _name) {
|
||||||
|
this.name = _name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set the value of the node.
|
||||||
|
* @param[in] _value New value of the node.
|
||||||
|
*/
|
||||||
|
public final void setValue(final String _value) {
|
||||||
|
this.value = _value;
|
||||||
|
}
|
||||||
|
};
|
@ -16,10 +16,10 @@ import org.atriasoft.exml.internal.Log;
|
|||||||
/**
|
/**
|
||||||
* List of all attribute element in a node
|
* List of all attribute element in a node
|
||||||
*/
|
*/
|
||||||
public abstract class AttributeList extends Node {
|
public abstract class XmlAttributeList extends XmlNode {
|
||||||
protected List<Attribute> listAttribute = new ArrayList<>(); //!< list of all attribute;
|
protected List<XmlAttribute> listAttribute = new ArrayList<>(); //!< list of all attribute;
|
||||||
|
|
||||||
public AttributeList() {
|
public XmlAttributeList() {
|
||||||
super();
|
super();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ public abstract class AttributeList extends Node {
|
|||||||
* Constructor
|
* Constructor
|
||||||
* @param[in] _value Node value;
|
* @param[in] _value Node value;
|
||||||
*/
|
*/
|
||||||
public AttributeList(final String _value) {
|
public XmlAttributeList(final String _value) {
|
||||||
super(_value);
|
super(_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ public abstract class AttributeList extends Node {
|
|||||||
* Add attribute on the List
|
* Add attribute on the List
|
||||||
* @param[in] _attr Pointer on the attribute
|
* @param[in] _attr Pointer on the attribute
|
||||||
*/
|
*/
|
||||||
public void appendAttribute(final Attribute _attr) {
|
public void appendAttribute(final XmlAttribute _attr) {
|
||||||
if (_attr == null) {
|
if (_attr == null) {
|
||||||
Log.error("Try to set an empty node");
|
Log.error("Try to set an empty node");
|
||||||
return;
|
return;
|
||||||
@ -82,7 +82,7 @@ public abstract class AttributeList extends Node {
|
|||||||
* @return Pointer on the attribute or NULL
|
* @return Pointer on the attribute or NULL
|
||||||
* @throws ExmlAttributeDoesNotExist The attribute does not exist.
|
* @throws ExmlAttributeDoesNotExist The attribute does not exist.
|
||||||
*/
|
*/
|
||||||
public Attribute getAttr(final int _id) throws ExmlAttributeDoesNotExist {
|
public XmlAttribute getAttr(final int _id) throws ExmlAttributeDoesNotExist {
|
||||||
if (_id < 0 || _id >= this.listAttribute.size()) {
|
if (_id < 0 || _id >= this.listAttribute.size()) {
|
||||||
throw new ExmlAttributeDoesNotExist("Attribute does not exist: " + _id + "/" + this.listAttribute.size());
|
throw new ExmlAttributeDoesNotExist("Attribute does not exist: " + _id + "/" + this.listAttribute.size());
|
||||||
}
|
}
|
||||||
@ -107,7 +107,7 @@ public abstract class AttributeList extends Node {
|
|||||||
throw new ExmlAttributeDoesNotExist("Attribute does not exist: " + _name + " in " + this.listAttribute.size() + " attributes");
|
throw new ExmlAttributeDoesNotExist("Attribute does not exist: " + _name + " in " + this.listAttribute.size() + " attributes");
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Attribute> getAttributes() {
|
public List<XmlAttribute> getAttributes() {
|
||||||
return this.listAttribute;
|
return this.listAttribute;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,7 +118,7 @@ public abstract class AttributeList extends Node {
|
|||||||
* @throws ExmlAttributeDoesNotExist The attribute does not exist.
|
* @throws ExmlAttributeDoesNotExist The attribute does not exist.
|
||||||
*/
|
*/
|
||||||
public Pair<String, String> getAttrPair(final int _id) throws ExmlAttributeDoesNotExist {
|
public Pair<String, String> getAttrPair(final int _id) throws ExmlAttributeDoesNotExist {
|
||||||
final Attribute att = getAttr(_id);
|
final XmlAttribute att = getAttr(_id);
|
||||||
return new Pair<String, String>(att.getName(), att.getValue());
|
return new Pair<String, String>(att.getName(), att.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,8 +142,8 @@ public abstract class AttributeList extends Node {
|
|||||||
if (_name.length() == 0) {
|
if (_name.length() == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (final ListIterator<Attribute> iter = this.listAttribute.listIterator(); iter.hasNext();) {
|
for (final ListIterator<XmlAttribute> iter = this.listAttribute.listIterator(); iter.hasNext();) {
|
||||||
final Attribute element = iter.next();
|
final XmlAttribute element = iter.next();
|
||||||
if (element == null) {
|
if (element == null) {
|
||||||
iter.remove();
|
iter.remove();
|
||||||
continue;
|
continue;
|
||||||
@ -170,7 +170,7 @@ public abstract class AttributeList extends Node {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final Attribute attr = new Attribute(_name, _value);
|
final XmlAttribute attr = new XmlAttribute(_name, _value);
|
||||||
this.listAttribute.add(attr);
|
this.listAttribute.add(attr);
|
||||||
}
|
}
|
||||||
|
|
50
src/org/atriasoft/exml/XmlComment.java
Normal file
50
src/org/atriasoft/exml/XmlComment.java
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/** @file
|
||||||
|
* @author Edouard DUPIN
|
||||||
|
* @copyright 2021, Edouard DUPIN, all right reserved
|
||||||
|
* @license MPL v2.0 (see license file)
|
||||||
|
*/
|
||||||
|
package org.atriasoft.exml;
|
||||||
|
|
||||||
|
import org.atriasoft.exml.internal.Tools;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Comment node: lt;!-- ... --gt;
|
||||||
|
*/
|
||||||
|
public class XmlComment extends XmlNode {
|
||||||
|
|
||||||
|
public XmlComment() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param[in] _value comment value
|
||||||
|
*/
|
||||||
|
public XmlComment(final String _value) {
|
||||||
|
super(_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public XmlComment(final XmlComment obj) {
|
||||||
|
super(obj.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlComment clone() {
|
||||||
|
return new XmlComment(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlNodeType getType() {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
72
src/org/atriasoft/exml/XmlDeclaration.java
Normal file
72
src/org/atriasoft/exml/XmlDeclaration.java
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/** @file
|
||||||
|
* @author Edouard DUPIN
|
||||||
|
* @copyright 2021, Edouard DUPIN, all right reserved
|
||||||
|
* @license MPL v2.0 (see license file)
|
||||||
|
*/
|
||||||
|
package org.atriasoft.exml;
|
||||||
|
|
||||||
|
import org.atriasoft.exml.internal.Log;
|
||||||
|
import org.atriasoft.exml.internal.Tools;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Declaration node: lt;?XXXXXX ... gt;
|
||||||
|
*/
|
||||||
|
public class XmlDeclaration extends XmlAttributeList {
|
||||||
|
public XmlDeclaration() {
|
||||||
|
super("");
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param[in] _name name of the declaration (xml, xml:xxxx ...)
|
||||||
|
*/
|
||||||
|
public XmlDeclaration(final String _name) {
|
||||||
|
super(_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public XmlDeclaration(final String _version, final String _format, final boolean _standalone) {
|
||||||
|
super("xml");
|
||||||
|
if (_version.isEmpty() != true) {
|
||||||
|
setAttribute("version", _version);
|
||||||
|
}
|
||||||
|
if (_format.contentEquals("UTF-8")) {
|
||||||
|
setAttribute("encoding", "UTF-8");
|
||||||
|
} else {
|
||||||
|
Log.error("Actually does not supported other charset than UTF8");
|
||||||
|
setAttribute("encoding", "UTF-8");
|
||||||
|
}
|
||||||
|
if (_standalone == true) {
|
||||||
|
setAttribute("standalone", "true");
|
||||||
|
} else {
|
||||||
|
setAttribute("standalone", "true");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public XmlDeclaration(final XmlDeclaration obj) {
|
||||||
|
super(obj.value);
|
||||||
|
for (final XmlAttribute elem : obj.listAttribute) {
|
||||||
|
this.listAttribute.add(elem.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlDeclaration clone() {
|
||||||
|
return new XmlDeclaration(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
251
src/org/atriasoft/exml/XmlElement.java
Normal file
251
src/org/atriasoft/exml/XmlElement.java
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
/** @file
|
||||||
|
* @author Edouard DUPIN
|
||||||
|
* @copyright 2021, Edouard DUPIN, all right reserved
|
||||||
|
* @license MPL v2.0 (see license file)
|
||||||
|
*/
|
||||||
|
package org.atriasoft.exml;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/** @file
|
||||||
|
* @author Edouard DUPIN
|
||||||
|
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||||
|
* @license MPL v2.0 (see license file)
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Basic element Node of an XML document lt;YYYYYgt;
|
||||||
|
*/
|
||||||
|
public class XmlElement extends XmlAttributeList {
|
||||||
|
protected List<XmlNode> listSub = new ArrayList<>(); //!< List of subNodes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
public XmlElement() {
|
||||||
|
super();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param[in] _value Element name;
|
||||||
|
*/
|
||||||
|
public XmlElement(final String _value) {
|
||||||
|
super(_value);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public XmlElement(final XmlElement obj) throws CloneNotSupportedException {
|
||||||
|
super(obj.value);
|
||||||
|
for (final XmlAttribute elem : obj.listAttribute) {
|
||||||
|
this.listAttribute.add(elem.clone());
|
||||||
|
}
|
||||||
|
for (final XmlNode elem : obj.listSub) {
|
||||||
|
this.listSub.add(elem.clone());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* add a node at the element (not Attribute (move in the attribute automaticly).
|
||||||
|
* @param[in] _node Pointer of the node to add.
|
||||||
|
*/
|
||||||
|
public void append(final XmlNode _node) {
|
||||||
|
if (_node == null) {
|
||||||
|
Log.error("Try to set an empty node");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int iii = 0; iii < this.listSub.size(); iii++) {
|
||||||
|
if (this.listSub.get(iii) == _node) {
|
||||||
|
Log.error("Try to add a node that is already added before !!!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.listSub.add(_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
super.clear();
|
||||||
|
this.listSub.clear();
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement clone() throws CloneNotSupportedException {
|
||||||
|
return new XmlElement(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the Node pointer of the element id.
|
||||||
|
* @param[in] _id Id of the element.
|
||||||
|
* @return true if the Node exist.
|
||||||
|
*/
|
||||||
|
public boolean existNode(final int _id) {
|
||||||
|
if (_id < 0 || _id >= this.listSub.size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get an element with his name (work only with Element)
|
||||||
|
* @param[in] _name Name of the element that is requested
|
||||||
|
* @return true if the Node exist.
|
||||||
|
*/
|
||||||
|
public boolean existNode(final String _name) {
|
||||||
|
if (_name.isEmpty() == true) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (int iii = 0; iii < this.listSub.size(); iii++) {
|
||||||
|
if (this.listSub.get(iii) != null && this.listSub.get(iii).getValue().contentEquals(_name) == true) {
|
||||||
|
if (this.listSub.get(iii) == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the Node pointer of the element id.
|
||||||
|
* @param[in] _id Id of the element.
|
||||||
|
* @return Pointer on node.
|
||||||
|
* @throws ExmlNodeDoesNotExist The Node does not exist
|
||||||
|
*/
|
||||||
|
public XmlNode getNode(final int _id) throws ExmlNodeDoesNotExist {
|
||||||
|
if (_id < 0 || _id >= this.listSub.size()) {
|
||||||
|
throw new ExmlNodeDoesNotExist("Node does not exist: " + _id + "/" + this.listSub.size());
|
||||||
|
}
|
||||||
|
return this.listSub.get(_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get an element with his name (work only with Element)
|
||||||
|
* @param[in] _name Name of the element that is requested
|
||||||
|
* @return Pointer on the node.
|
||||||
|
* @throws ExmlNodeDoesNotExist The Node does not exist
|
||||||
|
*/
|
||||||
|
public XmlNode getNode(final String _name) throws ExmlNodeDoesNotExist {
|
||||||
|
if (_name.isEmpty() == true) {
|
||||||
|
throw new ExmlNodeDoesNotExist("Node can not have empty name in " + this.listAttribute.size() + " nodes");
|
||||||
|
}
|
||||||
|
for (int iii = 0; iii < this.listSub.size(); iii++) {
|
||||||
|
if (this.listSub.get(iii) != null && this.listSub.get(iii).getValue().contentEquals(_name) == true) {
|
||||||
|
return this.listSub.get(iii);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new ExmlNodeDoesNotExist("Node does not exist: '" + _name + "' in " + this.listAttribute.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of the sub-nodes.
|
||||||
|
* @return List of current nodes.
|
||||||
|
*/
|
||||||
|
public List<XmlNode> getNodes() {
|
||||||
|
return 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...
|
||||||
|
*/
|
||||||
|
public String getText() {
|
||||||
|
final StringBuilder res = new StringBuilder();
|
||||||
|
if (this.listSub.size() == 1) {
|
||||||
|
if (this.listSub.get(0).getType() == XmlNodeType.TEXT) {
|
||||||
|
res.append(this.listSub.get(0).getValue());
|
||||||
|
} else {
|
||||||
|
this.listSub.get(0).iGenerate(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlNodeType getType() {
|
||||||
|
return XmlNodeType.ELEMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the type of the element id.
|
||||||
|
* @param[in] _id Id of the element.
|
||||||
|
* @return the Current type of the element or typeUnknow.
|
||||||
|
* @throws ExmlNodeDoesNotExist The Node does not exist
|
||||||
|
*/
|
||||||
|
public XmlNodeType getType(final int _id) throws ExmlNodeDoesNotExist {
|
||||||
|
if (_id < 0 || _id >= this.listSub.size()) {
|
||||||
|
throw new ExmlNodeDoesNotExist("Node does not exist: " + _id + "/" + this.listSub.size());
|
||||||
|
}
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
public void remove(final String _nodeName) {
|
||||||
|
if (_nodeName == "") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (final ListIterator<XmlNode> iter = this.listSub.listIterator(); iter.hasNext();) {
|
||||||
|
final XmlNode element = iter.next();
|
||||||
|
if (element == null) {
|
||||||
|
iter.remove();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (element.getValue().contentEquals(_nodeName) == true) {
|
||||||
|
iter.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the number of sub element in the node (can be Comment ; Element ; Text :Declaration).
|
||||||
|
* @return a number >=0.
|
||||||
|
*/
|
||||||
|
public int size() {
|
||||||
|
return this.listSub.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
@ -5,12 +5,12 @@
|
|||||||
*/
|
*/
|
||||||
package org.atriasoft.exml;
|
package org.atriasoft.exml;
|
||||||
|
|
||||||
import org.atriasoft.exml.internal.PositionParsing;
|
import org.atriasoft.exml.internal.FilePos;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Basic main object of all xml elements.
|
* Basic main object of all xml elements.
|
||||||
*/
|
*/
|
||||||
public abstract class Node {
|
public abstract class XmlNode {
|
||||||
|
|
||||||
protected FilePos pos; //!< position in the read file (null if the file is not parsed)
|
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 ...);
|
protected String value; //!< value of the node (for element this is the name, for text it is the inside text ...);
|
||||||
@ -18,7 +18,7 @@ public abstract class Node {
|
|||||||
/**
|
/**
|
||||||
* basic element of a xml structure
|
* basic element of a xml structure
|
||||||
*/
|
*/
|
||||||
public Node() {
|
public XmlNode() {
|
||||||
this.pos = null;
|
this.pos = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ public abstract class Node {
|
|||||||
* basic element of a xml structure
|
* basic element of a xml structure
|
||||||
* @param[in] _value value of the node
|
* @param[in] _value value of the node
|
||||||
*/
|
*/
|
||||||
public Node(final String _value) {
|
public XmlNode(final String _value) {
|
||||||
this.pos = null;
|
this.pos = null;
|
||||||
this.value = _value;
|
this.value = _value;
|
||||||
}
|
}
|
||||||
@ -40,7 +40,7 @@ public abstract class Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Node clone() throws CloneNotSupportedException {
|
protected XmlNode clone() throws CloneNotSupportedException {
|
||||||
throw new CloneNotSupportedException("Can not clone an abstract class ...");
|
throw new CloneNotSupportedException("Can not clone an abstract class ...");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ public abstract class Node {
|
|||||||
* get the node type.
|
* get the node type.
|
||||||
* @return the type of the Node.
|
* @return the type of the Node.
|
||||||
*/
|
*/
|
||||||
public abstract NodeType getType();
|
public abstract XmlNodeType getType();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get the current element Value.
|
* get the current element Value.
|
||||||
@ -83,14 +83,14 @@ public abstract class Node {
|
|||||||
* @param[in,out] _doc Base document reference
|
* @param[in,out] _doc Base document reference
|
||||||
* @return false if an error occured.
|
* @return false if an error occured.
|
||||||
*/
|
*/
|
||||||
protected abstract boolean iParse(String _data, PositionParsing _pos, boolean _caseSensitive, FilePos _filePos, Document _doc);
|
//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
|
* @return true if the node is a Comment
|
||||||
*/
|
*/
|
||||||
public final boolean isComment() {
|
public final boolean isComment() {
|
||||||
return this instanceof Comment;
|
return this instanceof XmlComment;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -98,7 +98,7 @@ public abstract class Node {
|
|||||||
* @return true if the node is a Declaration
|
* @return true if the node is a Declaration
|
||||||
*/
|
*/
|
||||||
public final boolean isDeclaration() {
|
public final boolean isDeclaration() {
|
||||||
return this instanceof Declaration;
|
return this instanceof XmlDeclaration;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -114,7 +114,7 @@ public abstract class Node {
|
|||||||
* @return true if the node is a Element
|
* @return true if the node is a Element
|
||||||
*/
|
*/
|
||||||
public final boolean isElement() {
|
public final boolean isElement() {
|
||||||
return this instanceof Element;
|
return this instanceof XmlElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -122,7 +122,7 @@ public abstract class Node {
|
|||||||
* @return true if the node is a Text
|
* @return true if the node is a Text
|
||||||
*/
|
*/
|
||||||
public final boolean isText() {
|
public final boolean isText() {
|
||||||
return this instanceof Text;
|
return this instanceof XmlText;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -138,16 +138,16 @@ public abstract class Node {
|
|||||||
* Cast the element in a Comment if it is possible.
|
* Cast the element in a Comment if it is possible.
|
||||||
* @return pointer on the class or null.
|
* @return pointer on the class or null.
|
||||||
*/
|
*/
|
||||||
public final Comment toComment() {
|
public final XmlComment toComment() {
|
||||||
return (Comment) this;
|
return (XmlComment) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cast the element in a Declaration if it is possible.
|
* Cast the element in a Declaration if it is possible.
|
||||||
* @return pointer on the class or null.
|
* @return pointer on the class or null.
|
||||||
*/
|
*/
|
||||||
public final Declaration toDeclaration() {
|
public final XmlDeclaration toDeclaration() {
|
||||||
return (Declaration) this;
|
return (XmlDeclaration) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -162,16 +162,16 @@ public abstract class Node {
|
|||||||
* Cast the element in a Element if it is possible.
|
* Cast the element in a Element if it is possible.
|
||||||
* @return pointer on the class or null.
|
* @return pointer on the class or null.
|
||||||
*/
|
*/
|
||||||
public final Element toElement() {
|
public final XmlElement toElement() {
|
||||||
return (Element) this;
|
return (XmlElement) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cast the element in a Text if it is possible.
|
* Cast the element in a Text if it is possible.
|
||||||
* @return pointer on the class or null.
|
* @return pointer on the class or null.
|
||||||
*/
|
*/
|
||||||
public final Text toText() {
|
public final XmlText toText() {
|
||||||
return (Text) this;
|
return (XmlText) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -8,7 +8,7 @@ package org.atriasoft.exml;
|
|||||||
/**
|
/**
|
||||||
* Type of the XML elements.
|
* Type of the XML elements.
|
||||||
*/
|
*/
|
||||||
public enum NodeType {
|
public enum XmlNodeType {
|
||||||
DOCUMENT, //!< all the file main access
|
DOCUMENT, //!< all the file main access
|
||||||
DECLARATION, //!< <?xml ... ?>
|
DECLARATION, //!< <?xml ... ?>
|
||||||
ELEMENT, //!< the <XXX> ... </XXX>
|
ELEMENT, //!< the <XXX> ... </XXX>
|
51
src/org/atriasoft/exml/XmlText.java
Normal file
51
src/org/atriasoft/exml/XmlText.java
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/** @file
|
||||||
|
* @author Edouard DUPIN
|
||||||
|
* @copyright 2021, Edouard DUPIN, all right reserved
|
||||||
|
* @license MPL v2.0 (see license file)
|
||||||
|
*/
|
||||||
|
package org.atriasoft.exml;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Text node interface (internal data between two Marker: <XXX> ALL here </XXX>
|
||||||
|
*/
|
||||||
|
public class XmlText extends XmlNode {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
public XmlText() {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param[in] _data String data of the current Text
|
||||||
|
*/
|
||||||
|
public XmlText(final String _data) {
|
||||||
|
super(_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* count the number of line in the current text
|
||||||
|
* @return The number of lines
|
||||||
|
*/
|
||||||
|
protected int countLines() {
|
||||||
|
int count = 1;
|
||||||
|
for (int iii = 0; iii < this.value.length(); iii++) {
|
||||||
|
if (this.value.charAt(iii) == '\n') {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlNodeType getType() {
|
||||||
|
return XmlNodeType.TEXT;
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean iGenerate(final StringBuilder _data, final int _indent) {
|
||||||
|
_data.append(replaceSpecialCharOut(this.value));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
65
src/org/atriasoft/exml/builder/Builder.java
Normal file
65
src/org/atriasoft/exml/builder/Builder.java
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
package org.atriasoft.exml.builder;
|
||||||
|
|
||||||
|
import org.atriasoft.exml.exception.ExmlBuilderException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author heero
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @author heero
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface Builder {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* New comment added on this Element
|
||||||
|
* @param element Element representing the node of the Comment is added
|
||||||
|
* @param comment Comment value
|
||||||
|
* @throws ExmlBuilderException Error with this node or element.
|
||||||
|
*/
|
||||||
|
void newComment(Object element, String comment) throws ExmlBuilderException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* New comment added on this Element
|
||||||
|
* @param parent Element representing the node of the Declaration is added
|
||||||
|
* @param text Name of the declaration
|
||||||
|
* @return Declaration object value
|
||||||
|
* @throws ExmlBuilderException Error with this node or element.
|
||||||
|
*/
|
||||||
|
Object newDeclaration(Object parent, String text) throws ExmlBuilderException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new sub-element on the current parent element
|
||||||
|
* @param parent Element representing the node of the Element is added
|
||||||
|
* @param nodeName New element name.
|
||||||
|
* @return the object representing the Element.
|
||||||
|
* @throws ExmlBuilderException Error with this node or element.
|
||||||
|
*/
|
||||||
|
Object newElement(Object parent, String nodeName) throws ExmlBuilderException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a property on the Element.
|
||||||
|
* @param element Element representing the node of the property is added
|
||||||
|
* @param propertyName Name of the property
|
||||||
|
* @param propertyValue Value of the property
|
||||||
|
* @throws ExmlBuilderException Error with this node or element.
|
||||||
|
*/
|
||||||
|
void newProperty(Object element, String propertyName, String propertyValue) throws ExmlBuilderException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create or get the root element of the document
|
||||||
|
* @return An object that id a root element.
|
||||||
|
* @throws ExmlBuilderException Error with this node or element.
|
||||||
|
*/
|
||||||
|
Object newRoot() throws ExmlBuilderException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a text value on the current Element
|
||||||
|
* @param parent Parent element where the Text is added
|
||||||
|
* @param text Test to add.
|
||||||
|
* @throws ExmlBuilderException Error with this node or element.
|
||||||
|
*/
|
||||||
|
void newText(Object parent, String text) throws ExmlBuilderException;
|
||||||
|
|
||||||
|
}
|
69
src/org/atriasoft/exml/builder/BuilderGeneric.java
Normal file
69
src/org/atriasoft/exml/builder/BuilderGeneric.java
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
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;
|
||||||
|
|
||||||
|
public class BuilderGeneric implements Builder {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void newComment(final Object element, final String comment) throws ExmlBuilderException {
|
||||||
|
if (element instanceof XmlElement) {
|
||||||
|
final XmlElement elem = (XmlElement) element;
|
||||||
|
elem.append(new XmlComment(comment));
|
||||||
|
}
|
||||||
|
throw new ExmlBuilderException("can not add Comment on something else than Element");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object newDeclaration(final Object parent, final String text) throws ExmlBuilderException {
|
||||||
|
if (parent instanceof XmlElement) {
|
||||||
|
final XmlElement elem = (XmlElement) parent;
|
||||||
|
final XmlDeclaration dec = new XmlDeclaration(text);
|
||||||
|
elem.append(dec);
|
||||||
|
return dec;
|
||||||
|
}
|
||||||
|
throw new ExmlBuilderException("can not add Declaration on something else than Element");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object newElement(final Object parent, final String nodeName) throws ExmlBuilderException {
|
||||||
|
if (parent instanceof XmlElement) {
|
||||||
|
final XmlElement elem = (XmlElement) parent;
|
||||||
|
final XmlElement eee = new XmlElement(nodeName);
|
||||||
|
elem.append(eee);
|
||||||
|
return eee;
|
||||||
|
}
|
||||||
|
throw new ExmlBuilderException("can not add Element on something else than Element");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void newProperty(final Object element, final String propertyName, final String propertyValue) throws ExmlBuilderException {
|
||||||
|
if (element instanceof XmlAttributeList) {
|
||||||
|
final XmlAttributeList attr = (XmlAttributeList) element;
|
||||||
|
attr.appendAttribute(new XmlAttribute(propertyName, propertyValue));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new ExmlBuilderException("can not add Attribute on something else than Element or Declaration");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object newRoot() throws ExmlBuilderException {
|
||||||
|
return new XmlElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void newText(final Object parent, final String text) throws ExmlBuilderException {
|
||||||
|
if (parent instanceof XmlElement) {
|
||||||
|
final XmlElement attr = (XmlElement) parent;
|
||||||
|
attr.append(new XmlText(text));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new ExmlBuilderException("can not add Text on something else than Element or Declaration");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
18
src/org/atriasoft/exml/exception/ExmlBuilderException.java
Normal file
18
src/org/atriasoft/exml/exception/ExmlBuilderException.java
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
/** @file
|
||||||
|
* @author Edouard DUPIN
|
||||||
|
* @copyright 2021, Edouard DUPIN, all right reserved
|
||||||
|
* @license MPL v2.0 (see license file)
|
||||||
|
*/
|
||||||
|
package org.atriasoft.exml.exception;
|
||||||
|
|
||||||
|
public class ExmlBuilderException extends ExmlException {
|
||||||
|
/**
|
||||||
|
* Generate Unique ID for serialization
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public ExmlBuilderException(final String data) {
|
||||||
|
super(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -3,7 +3,7 @@
|
|||||||
* @copyright 2021, Edouard DUPIN, all right reserved
|
* @copyright 2021, Edouard DUPIN, all right reserved
|
||||||
* @license MPL v2.0 (see license file)
|
* @license MPL v2.0 (see license file)
|
||||||
*/
|
*/
|
||||||
package org.atriasoft.exml;
|
package org.atriasoft.exml.internal;
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
* @author Edouard DUPIN
|
* @author Edouard DUPIN
|
@ -1,7 +1,5 @@
|
|||||||
package org.atriasoft.exml.internal;
|
package org.atriasoft.exml.internal;
|
||||||
|
|
||||||
import org.atriasoft.exml.FilePos;
|
|
||||||
|
|
||||||
public class Tools {
|
public class Tools {
|
||||||
/**
|
/**
|
||||||
* add indentation of the string input.
|
* add indentation of the string input.
|
||||||
@ -90,6 +88,37 @@ public class Tools {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String extract_line(final String data, final int _pos) {
|
||||||
|
// search back : '\n'
|
||||||
|
int startPos = data.lastIndexOf('\n', _pos);
|
||||||
|
if (startPos == _pos) {
|
||||||
|
startPos = 0;
|
||||||
|
} else {
|
||||||
|
startPos++;
|
||||||
|
}
|
||||||
|
// search forward : '\n'
|
||||||
|
int stopPos = _pos;
|
||||||
|
if (data.length() == _pos) {
|
||||||
|
stopPos = _pos;
|
||||||
|
} else if (data.charAt(_pos) != '\n') {
|
||||||
|
stopPos = data.indexOf('\n', _pos);
|
||||||
|
if (stopPos == _pos) {
|
||||||
|
stopPos = data.length();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (startPos == -1) {
|
||||||
|
startPos = 0;
|
||||||
|
} else if (startPos >= data.length()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (stopPos == -1) {
|
||||||
|
return "";
|
||||||
|
} else if (stopPos >= data.length()) {
|
||||||
|
stopPos = data.length();
|
||||||
|
}
|
||||||
|
return data.substring(startPos, stopPos);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isWhiteChar(final Character _val) {
|
public static boolean isWhiteChar(final Character _val) {
|
||||||
if (_val == ' ' || _val == '\t' || _val == '\n' || _val == '\r') {
|
if (_val == ' ' || _val == '\t' || _val == '\n' || _val == '\r') {
|
||||||
return true;
|
return true;
|
||||||
@ -97,5 +126,33 @@ public class Tools {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// transform the Text with :
|
||||||
|
// "<" == "<"
|
||||||
|
// ">" == ">"
|
||||||
|
// "&" == "&"
|
||||||
|
// "'" == "'"
|
||||||
|
// """ == """
|
||||||
|
public static String replaceSpecialChar(final String _inval) {
|
||||||
|
final String out = _inval;
|
||||||
|
out.replace("<", "<");
|
||||||
|
out.replace(">", ">");
|
||||||
|
out.replace("'", "'");
|
||||||
|
out.replace(""", "\"");
|
||||||
|
out.replace("&", "&");
|
||||||
|
//EXML_ERROR("INNN '"<< _inval << "' => '" << out << "'");
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String replaceSpecialCharOut(final String _inval) {
|
||||||
|
final String out = _inval;
|
||||||
|
out.replace("<", "<");
|
||||||
|
out.replace(">", ">");
|
||||||
|
out.replace("'", "'");
|
||||||
|
out.replace("\"", """);
|
||||||
|
out.replace("&", "&");
|
||||||
|
//EXML_ERROR("OUTTT '"<< _inval << "' => '" << out << "'");
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
private Tools() {}
|
private Tools() {}
|
||||||
}
|
}
|
||||||
|
517
src/org/atriasoft/exml/parser/ParseXml.java
Normal file
517
src/org/atriasoft/exml/parser/ParseXml.java
Normal file
@ -0,0 +1,517 @@
|
|||||||
|
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.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
|
||||||
|
private final Builder builder;
|
||||||
|
|
||||||
|
public ParseXml(final Builder builder) {
|
||||||
|
this.builder = builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean iParseAttribute(final Object parent, final String _data, final PositionParsing _pos, final FilePos _filePos, final ParsingProperty parsingProperty) throws ExmlBuilderException {
|
||||||
|
Log.verbose("start parse : 'attribute'");
|
||||||
|
final FilePos pos = _filePos.clone();
|
||||||
|
// search end of the comment :
|
||||||
|
int lastElementName = _pos.value;
|
||||||
|
for (int iii = _pos.value; iii < _data.length(); iii++) {
|
||||||
|
_filePos.check(_data.charAt(iii));
|
||||||
|
Tools.drawElementParsed(_data.charAt(iii), _filePos);
|
||||||
|
if (Tools.checkAvaillable(_data.charAt(iii), false) == true) {
|
||||||
|
lastElementName = iii;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String name = _data.substring(_pos.value, lastElementName + 1);
|
||||||
|
String value = "";
|
||||||
|
if (parsingProperty.getCaseSensitive() == true) {
|
||||||
|
name = name.toLowerCase();
|
||||||
|
}
|
||||||
|
// 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...");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (_data.charAt(lastElementName + white + 1) != '=') {
|
||||||
|
parsingProperty.createError(_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...");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
boolean simpleQuoteCase = false;
|
||||||
|
if (_data.charAt(lastElementName + white + 2) == '\'') { // '
|
||||||
|
simpleQuoteCase = true;
|
||||||
|
}
|
||||||
|
if (_data.charAt(lastElementName + white + 2) != '"' && _data.charAt(lastElementName + white + 2) != '\'') { // '
|
||||||
|
// parse with no element " == > direct value separate with space ...
|
||||||
|
_filePos.increment();
|
||||||
|
int lastAttributePos = lastElementName + white + 2;
|
||||||
|
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");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (_data.charAt(iii) != ' ' && _data.charAt(iii) != '/' && _data.charAt(iii) != '?' && _data.charAt(iii) != '>') {
|
||||||
|
lastAttributePos = iii + 1;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
value = _data.substring(lastElementName + white + 2, lastAttributePos);
|
||||||
|
|
||||||
|
//EXML_PARSE_ATTRIBUTE(pos << " attribute : " << name << "=\"" << value << "\"");
|
||||||
|
|
||||||
|
_pos.value = lastAttributePos - 1;
|
||||||
|
this.builder.newProperty(parent, name, value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
int lastAttributePos = lastElementName + white + 3;
|
||||||
|
for (int iii = lastElementName + white + 3; iii < _data.length(); iii++) {
|
||||||
|
Tools.drawElementParsed(_data.charAt(iii), _filePos);
|
||||||
|
_filePos.check(_data.charAt(iii));
|
||||||
|
if ((_data.charAt(iii) != '"' && simpleQuoteCase == false) || (_data.charAt(iii) != '\'' && simpleQuoteCase == true)) { // '
|
||||||
|
lastAttributePos = iii + 1;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
value = _data.substring(lastElementName + white + 3, lastAttributePos);
|
||||||
|
|
||||||
|
//EXML_PARSE_ATTRIBUTE(pos << " attribute : " << name << "=\"" << value << "\"");
|
||||||
|
|
||||||
|
_pos.value = lastAttributePos;
|
||||||
|
this.builder.newProperty(parent, name, value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean iParseCDATA(final Object parent, final String _data, final PositionParsing _pos, final FilePos _filePos, final ParsingProperty parsingProperty) throws ExmlBuilderException {
|
||||||
|
Log.verbose("start parse : 'text::CDATA'");
|
||||||
|
final FilePos pos = _filePos.clone();
|
||||||
|
// search end of the comment :
|
||||||
|
for (int iii = _pos.value; iii + 2 < _data.length(); iii++) {
|
||||||
|
Tools.drawElementParsed(_data.charAt(iii), _filePos);
|
||||||
|
if (_filePos.check(_data.charAt(iii)) == true) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (_data.charAt(iii) == ']' && _data.charAt(iii + 1) == ']' && _data.charAt(iii + 2) == '>') {
|
||||||
|
// find end of value:
|
||||||
|
_filePos.add(2);
|
||||||
|
final String valueCData = _data.substring(_pos.value, iii);
|
||||||
|
Log.verbose(" find text CDATA '" + valueCData + "'");
|
||||||
|
_pos.value = iii + 2;
|
||||||
|
this.builder.newText(parent, valueCData);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parsingProperty.createError(_data, _pos.value, _filePos, "text CDATA got end of file without finding end node");
|
||||||
|
_pos.value = _data.length();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean iParseComment(final Object parent, final String _data, final PositionParsing _pos, final FilePos _filePos, final ParsingProperty parsingProperty) throws ExmlBuilderException {
|
||||||
|
Log.verbose("start parse : 'comment'");
|
||||||
|
final FilePos pos = _filePos;
|
||||||
|
final FilePos tmpPos = new FilePos();
|
||||||
|
final int white = Tools.countWhiteChar(_data, _pos.value, tmpPos);
|
||||||
|
_filePos.add(tmpPos);
|
||||||
|
// search end of the comment :
|
||||||
|
for (int iii = _pos.value + white; iii + 2 < _data.length(); iii++) {
|
||||||
|
Tools.drawElementParsed(_data.charAt(iii), _filePos);
|
||||||
|
if (_filePos.check(_data.charAt(iii)) == true) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (_data.charAt(iii) == '-' && _data.charAt(iii + 1) == '-' && _data.charAt(iii + 2) == '>') {
|
||||||
|
_filePos.add(2);
|
||||||
|
// search whitespace :
|
||||||
|
int newEnd = iii;
|
||||||
|
for (int jjj = iii - 1; jjj > _pos.value; jjj--) {
|
||||||
|
if (Tools.isWhiteChar(_data.charAt(jjj)) == true) {
|
||||||
|
newEnd = jjj;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// find end of value:
|
||||||
|
final String value2 = _data.substring(_pos.value + white, newEnd);
|
||||||
|
Log.verbose(" find comment '" + value2 + "'");
|
||||||
|
this.builder.newComment(parent, value2);
|
||||||
|
_pos.value = iii + 2;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_pos.value = _data.length();
|
||||||
|
parsingProperty.createError(_data, _pos.value, _filePos, "comment got end of file without finding end node");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean iParseDeclaration(final Object parent, final String _data, final PositionParsing _pos, final FilePos _filePos, final ParsingProperty parsingProperty)
|
||||||
|
throws ExmlBuilderException {
|
||||||
|
final FilePos pos = _filePos;
|
||||||
|
// search end of the comment :
|
||||||
|
for (int iii = _pos.value; iii + 1 < _data.length(); iii++) {
|
||||||
|
Tools.drawElementParsed(_data.charAt(iii), _filePos);
|
||||||
|
if (_filePos.check(_data.charAt(iii)) == true) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (_data.charAt(iii) == '>' || _data.charAt(iii) == '<') {
|
||||||
|
// an error occured :
|
||||||
|
parsingProperty.createError(_data, _pos.value, _filePos, " find '>' or '<' instead of '?>'");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (_data.charAt(iii) == '?' && _data.charAt(iii + 1) == '>') {
|
||||||
|
_filePos.increment();
|
||||||
|
// find end of declaration:
|
||||||
|
_pos.value = iii + 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Tools.checkAvaillable(_data.charAt(iii), true) == true) {
|
||||||
|
// we find an attibute ==> parse it:
|
||||||
|
_pos.value = iii;
|
||||||
|
if (iParseAttribute(parent, _data, _pos, _filePos, parsingProperty) == false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
iii = _pos.value;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parsingProperty.createError(_data, _pos.value, _filePos, "Text got end of file without finding end node");
|
||||||
|
_pos.value = _data.length();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean iParseElement(final Object parent, final String nameElement, final String _data, final PositionParsing _pos, final FilePos _filePos, final ParsingProperty parsingProperty)
|
||||||
|
throws ExmlBuilderException {
|
||||||
|
// note : When start parsing the upper element must have set the value of the element and set the position after this one
|
||||||
|
final FilePos pos = _filePos.clone();
|
||||||
|
// find a normal node ...
|
||||||
|
for (int iii = _pos.value; iii < _data.length(); iii++) {
|
||||||
|
_filePos.check(_data.charAt(iii));
|
||||||
|
Tools.drawElementParsed(_data.charAt(iii), _filePos);
|
||||||
|
if (_data.charAt(iii) == '>') {
|
||||||
|
// we find the end ...
|
||||||
|
_pos.value = iii + 1;
|
||||||
|
return subParseElement(parent, nameElement, _data, _pos, _filePos, parsingProperty);
|
||||||
|
}
|
||||||
|
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");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// TODO : Can have white spaces ....
|
||||||
|
if (_data.charAt(iii + 1) == '>') {
|
||||||
|
_pos.value = iii + 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// error
|
||||||
|
parsingProperty.createError(_data, _pos.value, _filePos, "Find / without > char ...");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (Tools.checkAvaillable(_data.charAt(iii), true) == true) {
|
||||||
|
// we find an attibute ==> parse it:
|
||||||
|
_pos.value = iii;
|
||||||
|
if (iParseAttribute(parent, _data, _pos, _filePos, parsingProperty) == false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
iii = _pos.value;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (Tools.isWhiteChar(_data.charAt(iii)) == false) {
|
||||||
|
parsingProperty.createError(_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");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean iParseText(final Object parent, final String _data, final PositionParsing _pos, final FilePos _filePos, final ParsingProperty parsingProperty) throws ExmlBuilderException {
|
||||||
|
Log.verbose("start parse : 'text'");
|
||||||
|
final FilePos pos = _filePos.clone();
|
||||||
|
// search end of the comment :
|
||||||
|
for (int iii = _pos.value; iii < _data.length(); iii++) {
|
||||||
|
Tools.drawElementParsed(_data.charAt(iii), _filePos);
|
||||||
|
if (_filePos.check(_data.charAt(iii)) == true) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (_data.charAt(iii) == '>' || _data.charAt(iii) == '<') {
|
||||||
|
// search whitespace :
|
||||||
|
int newEnd = iii;
|
||||||
|
for (int jjj = iii - 1; jjj > _pos.value; --jjj) {
|
||||||
|
if (Tools.isWhiteChar(_data.charAt(jjj)) == true) {
|
||||||
|
newEnd = jjj;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// find end of value:
|
||||||
|
String valueText = _data.substring(_pos.value, newEnd);
|
||||||
|
Log.verbose("find text '" + valueText + "'");
|
||||||
|
_pos.value = iii - 1;
|
||||||
|
valueText = Tools.replaceSpecialChar(valueText);
|
||||||
|
this.builder.newText(parent, valueText);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parsingProperty.createError(_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 {
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse sub node string
|
||||||
|
* @param[in] _data all file string data
|
||||||
|
* @param[in,out] _pos Position to start parsing in the file and return the end of parsing
|
||||||
|
* @param[in] _caseSensitive Case sensitive parsing (usefull for html)
|
||||||
|
* @param[in] _filePos Current File position of the parsing
|
||||||
|
* @param[in] _doc Document base reference
|
||||||
|
* @param[in] _mainNode if true, this is the first root node
|
||||||
|
* @return true parsing is done OK
|
||||||
|
* @return false An error appear in the parsing
|
||||||
|
*/
|
||||||
|
protected boolean subParseElement(final Object parent, final String nameElement, final String _data, final PositionParsing _pos, final FilePos _filePos, final ParsingProperty parsingProperty)
|
||||||
|
throws ExmlBuilderException {
|
||||||
|
//EXML_PARSE_ELEMENT(" start subParse ... " << _pos << " " << _filePos);
|
||||||
|
for (int iii = _pos.value; iii < _data.length(); iii++) {
|
||||||
|
_filePos.check(_data.charAt(iii));
|
||||||
|
Tools.drawElementParsed(_data.charAt(iii), _filePos);
|
||||||
|
final FilePos tmpPos = new FilePos();
|
||||||
|
if (_data.charAt(iii) == '<') {
|
||||||
|
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");
|
||||||
|
_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...");
|
||||||
|
_pos.value = iii + white + 1;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (_data.charAt(iii + white + 1) == '?') {
|
||||||
|
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...");
|
||||||
|
_pos.value = iii + white + 1;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
//EXML_DEBUG("Generate node name : '" << _data[iii+1] << "'");
|
||||||
|
int endPosName = iii + white + 1;
|
||||||
|
// generate element name ...
|
||||||
|
for (int jjj = iii + white + 2; jjj < _data.length(); jjj++) {
|
||||||
|
if (Tools.checkAvaillable(_data.charAt(jjj), false) == true) {
|
||||||
|
// we find the end ...
|
||||||
|
endPosName = jjj;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tmpPos.check(_data.charAt(jjj));
|
||||||
|
}
|
||||||
|
String tmpname = _data.substring(iii + white + 2, endPosName + 1);
|
||||||
|
if (parsingProperty.getCaseSensitive() == true) {
|
||||||
|
tmpname = tmpname.toLowerCase();
|
||||||
|
}
|
||||||
|
// Find declaration marker
|
||||||
|
final Object declaration = this.builder.newDeclaration(parent, tmpname);
|
||||||
|
_filePos.add(tmpPos);
|
||||||
|
_pos.value = endPosName + 1;
|
||||||
|
Log.verbose("start parse : 'declaration' : '" + tmpname + "'");
|
||||||
|
if (iParseDeclaration(declaration, _data, _pos, _filePos, parsingProperty) == false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
iii = _pos.value;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (_data.charAt(iii + white + 1) == '!') {
|
||||||
|
tmpPos.increment();
|
||||||
|
// Find special block element
|
||||||
|
if (iii + white + 2 >= _data.length()) {
|
||||||
|
parsingProperty.createError(_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");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (_data.charAt(iii + white + 3) != '-') {
|
||||||
|
parsingProperty.createError(_data, _pos.value, _filePos, "Element parse with '<!-" + _data.charAt(iii + 3) + "' chars == > invalide XML");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
tmpPos.increment();
|
||||||
|
// find comment:
|
||||||
|
_pos.value = iii + white + 4;
|
||||||
|
_filePos.add(tmpPos);
|
||||||
|
if (iParseComment(parent, _data, _pos, _filePos, parsingProperty) == false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
iii = _pos.value;
|
||||||
|
} 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");
|
||||||
|
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");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
tmpPos.add(6);
|
||||||
|
// find text:
|
||||||
|
_pos.value = iii + 9 + white;
|
||||||
|
_filePos.add(tmpPos);
|
||||||
|
if (iParseCDATA(parent, _data, _pos, _filePos, parsingProperty) == false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
iii = _pos.value;
|
||||||
|
} else {
|
||||||
|
parsingProperty.createError(_data, _pos.value, _filePos, "End file with '<!" + _data.charAt(iii + white + 2) + "' chars == > invalide XML");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (_data.charAt(iii + white + 1) == '/') {
|
||||||
|
tmpPos.increment();
|
||||||
|
//EXML_DEBUG("Generate node name : '" << _data[iii+1] << "'");
|
||||||
|
int endPosName = iii + white + 1;
|
||||||
|
// generate element name ...
|
||||||
|
for (int jjj = iii + white + 2; jjj < _data.length(); jjj++) {
|
||||||
|
if (Tools.checkAvaillable(_data.charAt(jjj), false) == true) {
|
||||||
|
// we find the end ...
|
||||||
|
endPosName = jjj;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tmpPos.check(_data.charAt(jjj));
|
||||||
|
}
|
||||||
|
String tmpname = _data.substring(iii + white + 2, endPosName + 1);
|
||||||
|
if (parsingProperty.getCaseSensitive() == true) {
|
||||||
|
tmpname = tmpname.toLowerCase();
|
||||||
|
}
|
||||||
|
if (tmpname.contentEquals(nameElement) == true) {
|
||||||
|
// find end of node :
|
||||||
|
// find > element ...
|
||||||
|
for (int jjj = endPosName + 1; jjj < _data.length(); jjj++) {
|
||||||
|
Tools.drawElementParsed(_data.charAt(jjj), _filePos);
|
||||||
|
if (tmpPos.check(_data.charAt(jjj)) == true) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (_data.charAt(jjj) == '>') {
|
||||||
|
_pos.value = jjj;
|
||||||
|
_filePos.add(tmpPos);
|
||||||
|
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 + "'");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
parsingProperty.createError(_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");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Tools.checkAvaillable(_data.charAt(iii + white + 1), true) == true) {
|
||||||
|
tmpPos.increment();
|
||||||
|
Log.debug("Generate node name : '" + _data.charAt(iii + 1) + "'");
|
||||||
|
int endPosName = iii + white + 1;
|
||||||
|
// generate element name ...
|
||||||
|
for (int jjj = iii + white + 2; jjj < _data.length(); jjj++) {
|
||||||
|
if (Tools.checkAvaillable(_data.charAt(jjj), false) == true) {
|
||||||
|
// we find the end ...
|
||||||
|
endPosName = jjj;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tmpPos.check(_data.charAt(jjj));
|
||||||
|
}
|
||||||
|
String tmpname = _data.substring(iii + white + 1, endPosName + 1);
|
||||||
|
if (parsingProperty.getCaseSensitive() == true) {
|
||||||
|
tmpname = tmpname.toLowerCase();
|
||||||
|
}
|
||||||
|
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) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
iii = _pos.value;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
_filePos.add(tmpPos);
|
||||||
|
// here we have an error :
|
||||||
|
parsingProperty.createError(_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 ...");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// might to be data text ...
|
||||||
|
if (_data.charAt(iii) == '\n' || _data.charAt(iii) == ' ' || _data.charAt(iii) == '\t' || _data.charAt(iii) == '\r') {
|
||||||
|
// empty spaces == > nothing to do ....
|
||||||
|
} else {
|
||||||
|
// find data == > parse it...
|
||||||
|
_pos.value = iii;
|
||||||
|
_filePos.add(tmpPos);
|
||||||
|
if (iParseText(parent, _data, _pos, _filePos, parsingProperty) == false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
iii = _pos.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nameElement == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
parsingProperty.createError(_data, _pos.value, _filePos, "Did not find end of the exml::internal::Element : '" + nameElement + "'");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
87
src/org/atriasoft/exml/parser/ParsingProperty.java
Normal file
87
src/org/atriasoft/exml/parser/ParsingProperty.java
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
package org.atriasoft.exml.parser;
|
||||||
|
|
||||||
|
import org.atriasoft.exml.internal.FilePos;
|
||||||
|
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
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
public ParsingProperty() {
|
||||||
|
this.caseSensitive = false;
|
||||||
|
this.writeErrorWhenDetexted = true;
|
||||||
|
this.comment = "";
|
||||||
|
this.Line = "";
|
||||||
|
this.filePos = new FilePos(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request display in log of the error
|
||||||
|
*/
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the status of case sensitive mode.
|
||||||
|
* @return true if case sensitive is active
|
||||||
|
*/
|
||||||
|
public boolean getCaseSensitive() {
|
||||||
|
return this.caseSensitive;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the display of the error status.
|
||||||
|
* @return true Display error
|
||||||
|
* @return false Does not display error (get it at end)
|
||||||
|
*/
|
||||||
|
public boolean getDisplayError() {
|
||||||
|
return this.writeErrorWhenDetexted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the display of the error when detected.
|
||||||
|
* @param[in] _value true: display error, false not display error (get it at end)
|
||||||
|
*/
|
||||||
|
public void setDisplayError(final boolean _value) {
|
||||||
|
this.writeErrorWhenDetexted = _value;
|
||||||
|
}
|
||||||
|
}
|
@ -6,6 +6,7 @@
|
|||||||
package test.atriasoft.exml;
|
package test.atriasoft.exml;
|
||||||
|
|
||||||
import org.atriasoft.exml.Document;
|
import org.atriasoft.exml.Document;
|
||||||
|
import org.atriasoft.exml.Exml;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
|
||||||
class ExmlLocal {
|
class ExmlLocal {
|
||||||
@ -18,7 +19,7 @@ class ExmlLocal {
|
|||||||
final Document doc = new Document();
|
final Document doc = new Document();
|
||||||
//doc.setCaseSensitive(!_caseInSensitive);
|
//doc.setCaseSensitive(!_caseInSensitive);
|
||||||
Log.verbose("parse : \n" + _input);
|
Log.verbose("parse : \n" + _input);
|
||||||
final boolean retParse = doc.parse(_input);
|
final boolean retParse = Exml.parse(_input);
|
||||||
if (_errorPos == 1) {
|
if (_errorPos == 1) {
|
||||||
Assertions.assertEquals(retParse, false);
|
Assertions.assertEquals(retParse, false);
|
||||||
return;
|
return;
|
||||||
|
@ -5,9 +5,9 @@
|
|||||||
*/
|
*/
|
||||||
package test.atriasoft.exml;
|
package test.atriasoft.exml;
|
||||||
|
|
||||||
import org.atriasoft.exml.Attribute;
|
import org.atriasoft.exml.XmlAttribute;
|
||||||
import org.atriasoft.exml.Document;
|
import org.atriasoft.exml.Document;
|
||||||
import org.atriasoft.exml.Element;
|
import org.atriasoft.exml.XmlElement;
|
||||||
import org.atriasoft.exml.exception.ExmlAttributeDoesNotExist;
|
import org.atriasoft.exml.exception.ExmlAttributeDoesNotExist;
|
||||||
import org.atriasoft.exml.exception.ExmlNodeDoesNotExist;
|
import org.atriasoft.exml.exception.ExmlNodeDoesNotExist;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
@ -22,29 +22,29 @@ public class ExmlTestAttribute {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void AttributeElementNotExist() {
|
public void AttributeElementNotExist() {
|
||||||
final Element myElement = new Element("NodeName");
|
final XmlElement myElement = new XmlElement("NodeName");
|
||||||
Assertions.assertThrows(ExmlAttributeDoesNotExist.class, () -> myElement.getAttr(65465465));
|
Assertions.assertThrows(ExmlAttributeDoesNotExist.class, () -> myElement.getAttr(65465465));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void clear() {
|
public void clear() {
|
||||||
|
|
||||||
final Attribute myAttribute = new Attribute("nameAttribute", "valueAttribute");
|
final XmlAttribute myAttribute = new XmlAttribute("nameAttribute", "valueAttribute");
|
||||||
myAttribute.clear();
|
myAttribute.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void createAssignement() {
|
public void createAssignement() {
|
||||||
final Attribute myAttribute = new Attribute("nameAttribute", "valueAttribute");
|
final XmlAttribute myAttribute = new XmlAttribute("nameAttribute", "valueAttribute");
|
||||||
final Attribute myOtherAttribute = myAttribute.clone();
|
final XmlAttribute myOtherAttribute = myAttribute.clone();
|
||||||
Assertions.assertEquals(myAttribute.getValue(), myOtherAttribute.getValue());
|
Assertions.assertEquals(myAttribute.getValue(), myOtherAttribute.getValue());
|
||||||
Assertions.assertEquals(myAttribute.getName(), myOtherAttribute.getName());
|
Assertions.assertEquals(myAttribute.getName(), myOtherAttribute.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void createCopy() {
|
public void createCopy() {
|
||||||
final Attribute myAttribute = new Attribute("nameAttribute", "valueAttribute");
|
final XmlAttribute myAttribute = new XmlAttribute("nameAttribute", "valueAttribute");
|
||||||
final Attribute myOtherAttribute = new Attribute(myAttribute);
|
final XmlAttribute myOtherAttribute = new XmlAttribute(myAttribute);
|
||||||
Assertions.assertEquals(myAttribute.getValue(), myOtherAttribute.getValue());
|
Assertions.assertEquals(myAttribute.getValue(), myOtherAttribute.getValue());
|
||||||
Assertions.assertEquals(myAttribute.getName(), myOtherAttribute.getName());
|
Assertions.assertEquals(myAttribute.getName(), myOtherAttribute.getName());
|
||||||
}
|
}
|
||||||
@ -52,7 +52,7 @@ public class ExmlTestAttribute {
|
|||||||
@Test
|
@Test
|
||||||
public void exist() {
|
public void exist() {
|
||||||
|
|
||||||
final Element elem = new Element("elem");
|
final XmlElement elem = new XmlElement("elem");
|
||||||
elem.setAttribute("valA", "plop");
|
elem.setAttribute("valA", "plop");
|
||||||
Assertions.assertEquals(elem.existAttribute("valA"), true);
|
Assertions.assertEquals(elem.existAttribute("valA"), true);
|
||||||
Assertions.assertEquals(elem.existAttribute("qsdfsdf"), false);
|
Assertions.assertEquals(elem.existAttribute("qsdfsdf"), false);
|
||||||
@ -61,7 +61,7 @@ public class ExmlTestAttribute {
|
|||||||
@Test
|
@Test
|
||||||
public void get() {
|
public void get() {
|
||||||
|
|
||||||
final Element elem = new Element("elem");
|
final XmlElement elem = new XmlElement("elem");
|
||||||
elem.setAttribute("valA", "plop");
|
elem.setAttribute("valA", "plop");
|
||||||
try {
|
try {
|
||||||
Assertions.assertEquals(elem.getAttribute("valA"), "plop");
|
Assertions.assertEquals(elem.getAttribute("valA"), "plop");
|
||||||
@ -74,7 +74,7 @@ public class ExmlTestAttribute {
|
|||||||
@Test
|
@Test
|
||||||
public void getpair() {
|
public void getpair() {
|
||||||
|
|
||||||
final Element elem = new Element("elem");
|
final XmlElement elem = new XmlElement("elem");
|
||||||
elem.setAttribute("valA", "coucou");
|
elem.setAttribute("valA", "coucou");
|
||||||
try {
|
try {
|
||||||
Assertions.assertEquals(elem.getAttrPair(0).first, "valA");
|
Assertions.assertEquals(elem.getAttrPair(0).first, "valA");
|
||||||
@ -90,14 +90,14 @@ public class ExmlTestAttribute {
|
|||||||
public void moveInAllElement() {
|
public void moveInAllElement() {
|
||||||
final Document doc = new Document();
|
final Document doc = new Document();
|
||||||
doc.parse("<elem valA=\"plop\"/>");
|
doc.parse("<elem valA=\"plop\"/>");
|
||||||
Element elem;
|
XmlElement elem;
|
||||||
try {
|
try {
|
||||||
elem = (Element) doc.getNode("elem");
|
elem = (XmlElement) doc.getNode("elem");
|
||||||
} catch (final ExmlNodeDoesNotExist e) {
|
} catch (final ExmlNodeDoesNotExist e) {
|
||||||
Assertions.fail("Should Not have thrown an exception");
|
Assertions.fail("Should Not have thrown an exception");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (final Attribute it : elem.getAttributes()) {
|
for (final XmlAttribute it : elem.getAttributes()) {
|
||||||
Assertions.assertEquals(it.getName(), "valA");
|
Assertions.assertEquals(it.getName(), "valA");
|
||||||
Assertions.assertEquals(it.getValue(), "plop");
|
Assertions.assertEquals(it.getValue(), "plop");
|
||||||
}
|
}
|
||||||
@ -105,7 +105,7 @@ public class ExmlTestAttribute {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void remove() {
|
public void remove() {
|
||||||
final Element elem = new Element("elem");
|
final XmlElement elem = new XmlElement("elem");
|
||||||
elem.setAttribute("valA", "plop");
|
elem.setAttribute("valA", "plop");
|
||||||
Assertions.assertEquals(elem.existAttribute("valA"), true);
|
Assertions.assertEquals(elem.existAttribute("valA"), true);
|
||||||
elem.removeAttribute("valA");
|
elem.removeAttribute("valA");
|
||||||
@ -115,7 +115,7 @@ public class ExmlTestAttribute {
|
|||||||
@Test
|
@Test
|
||||||
public void setGetName() {
|
public void setGetName() {
|
||||||
|
|
||||||
final Attribute myAttribute = new Attribute("nameAttribute", "valueAttribute");
|
final XmlAttribute myAttribute = new XmlAttribute("nameAttribute", "valueAttribute");
|
||||||
Assertions.assertEquals(myAttribute.getName(), "nameAttribute");
|
Assertions.assertEquals(myAttribute.getName(), "nameAttribute");
|
||||||
myAttribute.setName("newName");
|
myAttribute.setName("newName");
|
||||||
Assertions.assertEquals(myAttribute.getName(), "newName");
|
Assertions.assertEquals(myAttribute.getName(), "newName");
|
||||||
@ -124,7 +124,7 @@ public class ExmlTestAttribute {
|
|||||||
@Test
|
@Test
|
||||||
public void setGetValue() {
|
public void setGetValue() {
|
||||||
|
|
||||||
final Attribute myAttribute = new Attribute("nameAttribute", "valueAttribute");
|
final XmlAttribute myAttribute = new XmlAttribute("nameAttribute", "valueAttribute");
|
||||||
Assertions.assertEquals(myAttribute.getValue(), "valueAttribute");
|
Assertions.assertEquals(myAttribute.getValue(), "valueAttribute");
|
||||||
myAttribute.setValue("new value");
|
myAttribute.setValue("new value");
|
||||||
Assertions.assertEquals(myAttribute.getValue(), "new value");
|
Assertions.assertEquals(myAttribute.getValue(), "new value");
|
||||||
@ -133,7 +133,7 @@ public class ExmlTestAttribute {
|
|||||||
@Test
|
@Test
|
||||||
public void setterNew() {
|
public void setterNew() {
|
||||||
|
|
||||||
final Element elem = new Element("elem");
|
final XmlElement elem = new XmlElement("elem");
|
||||||
elem.setAttribute("valA", "coucou");
|
elem.setAttribute("valA", "coucou");
|
||||||
try {
|
try {
|
||||||
Assertions.assertEquals(elem.getAttribute("valA"), "coucou");
|
Assertions.assertEquals(elem.getAttribute("valA"), "coucou");
|
||||||
@ -145,7 +145,7 @@ public class ExmlTestAttribute {
|
|||||||
@Test
|
@Test
|
||||||
public void setterRewrite() {
|
public void setterRewrite() {
|
||||||
|
|
||||||
final Element elem = new Element("elem");
|
final XmlElement elem = new XmlElement("elem");
|
||||||
elem.setAttribute("valA", "coucou");
|
elem.setAttribute("valA", "coucou");
|
||||||
try {
|
try {
|
||||||
Assertions.assertEquals(elem.getAttribute("valA"), "coucou");
|
Assertions.assertEquals(elem.getAttribute("valA"), "coucou");
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
package test.atriasoft.exml;
|
package test.atriasoft.exml;
|
||||||
|
|
||||||
import org.atriasoft.exml.Document;
|
import org.atriasoft.exml.Document;
|
||||||
import org.atriasoft.exml.Element;
|
import org.atriasoft.exml.XmlElement;
|
||||||
import org.atriasoft.exml.TextCDATA;
|
import org.atriasoft.exml.TextCDATA;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
@ -32,8 +32,8 @@ public class ExmlTestCData {
|
|||||||
public void parseCDATA() {
|
public void parseCDATA() {
|
||||||
final Document doc = new Document();
|
final Document doc = new Document();
|
||||||
doc.parse("<elem><![CDATA[Text &é<>examp]le]] ...]]></elem>");
|
doc.parse("<elem><![CDATA[Text &é<>examp]le]] ...]]></elem>");
|
||||||
final Element elem = Assertions.assertDoesNotThrow(() -> {
|
final XmlElement elem = Assertions.assertDoesNotThrow(() -> {
|
||||||
return (Element) doc.getNode("elem");
|
return (XmlElement) doc.getNode("elem");
|
||||||
});
|
});
|
||||||
Assertions.assertEquals("Text &é<>examp]le]] ...", elem.getText());
|
Assertions.assertEquals("Text &é<>examp]le]] ...", elem.getText());
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,9 @@
|
|||||||
*/
|
*/
|
||||||
package test.atriasoft.exml;
|
package test.atriasoft.exml;
|
||||||
|
|
||||||
import org.atriasoft.exml.Comment;
|
import org.atriasoft.exml.XmlComment;
|
||||||
import org.atriasoft.exml.Node;
|
import org.atriasoft.exml.XmlNode;
|
||||||
import org.atriasoft.exml.NodeType;
|
import org.atriasoft.exml.XmlNodeType;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
@ -20,28 +20,28 @@ public class ExmlTestComment {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void create() {
|
public void create() {
|
||||||
final Comment myComment = new Comment("my Comment");
|
final XmlComment myComment = new XmlComment("my Comment");
|
||||||
Assertions.assertEquals(myComment.getType(), NodeType.COMMENT);
|
Assertions.assertEquals(myComment.getType(), XmlNodeType.COMMENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void createAssignement() {
|
public void createAssignement() {
|
||||||
final Comment myComment = new Comment("my comment");
|
final XmlComment myComment = new XmlComment("my comment");
|
||||||
final Comment myOtherComment = myComment.clone();
|
final XmlComment myOtherComment = myComment.clone();
|
||||||
Assertions.assertEquals(myComment.getValue(), myOtherComment.getValue());
|
Assertions.assertEquals(myComment.getValue(), myOtherComment.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void createCopy() {
|
public void createCopy() {
|
||||||
final Comment myComment = new Comment("my Comment");
|
final XmlComment myComment = new XmlComment("my Comment");
|
||||||
final Comment myOtherComment = new Comment(myComment);
|
final XmlComment myOtherComment = new XmlComment(myComment);
|
||||||
Assertions.assertEquals(myComment.getValue(), myOtherComment.getValue());
|
Assertions.assertEquals(myComment.getValue(), myOtherComment.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void transform() {
|
public void transform() {
|
||||||
Comment myComment = new Comment("my comment");
|
XmlComment myComment = new XmlComment("my comment");
|
||||||
final Node myNode = myComment;
|
final XmlNode myNode = myComment;
|
||||||
myComment = myNode.toComment();
|
myComment = myNode.toComment();
|
||||||
Assertions.assertEquals(myComment.getValue(), "my comment");
|
Assertions.assertEquals(myComment.getValue(), "my comment");
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
package test.atriasoft.exml;
|
package test.atriasoft.exml;
|
||||||
|
|
||||||
import org.atriasoft.exml.DeclarationXML;
|
import org.atriasoft.exml.DeclarationXML;
|
||||||
import org.atriasoft.exml.NodeType;
|
import org.atriasoft.exml.XmlNodeType;
|
||||||
import org.atriasoft.exml.exception.ExmlAttributeDoesNotExist;
|
import org.atriasoft.exml.exception.ExmlAttributeDoesNotExist;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
@ -21,7 +21,7 @@ public class ExmlTestDeclarationXML {
|
|||||||
@Test
|
@Test
|
||||||
public void create() {
|
public void create() {
|
||||||
final DeclarationXML myDeclarationXML = new DeclarationXML("1.0", "UTF-8", true);
|
final DeclarationXML myDeclarationXML = new DeclarationXML("1.0", "UTF-8", true);
|
||||||
Assertions.assertEquals(myDeclarationXML.getType(), NodeType.DECLARATION);
|
Assertions.assertEquals(myDeclarationXML.getType(), XmlNodeType.DECLARATION);
|
||||||
try {
|
try {
|
||||||
Assertions.assertEquals(myDeclarationXML.getAttribute("version"), "1.0");
|
Assertions.assertEquals(myDeclarationXML.getAttribute("version"), "1.0");
|
||||||
Assertions.assertEquals(myDeclarationXML.getAttribute("encoding"), "UTF-8");
|
Assertions.assertEquals(myDeclarationXML.getAttribute("encoding"), "UTF-8");
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
package test.atriasoft.exml;
|
package test.atriasoft.exml;
|
||||||
|
|
||||||
import org.atriasoft.exml.Document;
|
import org.atriasoft.exml.Document;
|
||||||
import org.atriasoft.exml.Element;
|
import org.atriasoft.exml.XmlElement;
|
||||||
import org.atriasoft.exml.Node;
|
import org.atriasoft.exml.XmlNode;
|
||||||
import org.atriasoft.exml.NodeType;
|
import org.atriasoft.exml.XmlNodeType;
|
||||||
import org.atriasoft.exml.exception.ExmlNodeDoesNotExist;
|
import org.atriasoft.exml.exception.ExmlNodeDoesNotExist;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
@ -22,9 +22,9 @@ public class ExmlTestElement {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void append() {
|
public void append() {
|
||||||
final Element myElement = new Element("NodeName");
|
final XmlElement myElement = new XmlElement("NodeName");
|
||||||
Assertions.assertEquals(myElement.getNodes().size(), 0);
|
Assertions.assertEquals(myElement.getNodes().size(), 0);
|
||||||
myElement.append(new Element("jkjhkjhkh"));
|
myElement.append(new XmlElement("jkjhkjhkh"));
|
||||||
Assertions.assertEquals(myElement.getNodes().size(), 1);
|
Assertions.assertEquals(myElement.getNodes().size(), 1);
|
||||||
try {
|
try {
|
||||||
myElement.getNode("jkjhkjhkh");
|
myElement.getNode("jkjhkjhkh");
|
||||||
@ -36,9 +36,9 @@ public class ExmlTestElement {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void clear() {
|
public void clear() {
|
||||||
final Element myElement = new Element("NodeName");
|
final XmlElement myElement = new XmlElement("NodeName");
|
||||||
Assertions.assertEquals(myElement.getNodes().size(), 0);
|
Assertions.assertEquals(myElement.getNodes().size(), 0);
|
||||||
myElement.append(new Element("jkjhkjhkh"));
|
myElement.append(new XmlElement("jkjhkjhkh"));
|
||||||
Assertions.assertEquals(myElement.getNodes().size(), 1);
|
Assertions.assertEquals(myElement.getNodes().size(), 1);
|
||||||
try {
|
try {
|
||||||
myElement.getNode("jkjhkjhkh");
|
myElement.getNode("jkjhkjhkh");
|
||||||
@ -52,15 +52,15 @@ public class ExmlTestElement {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void create() {
|
public void create() {
|
||||||
final Element myElement = new Element("NodeName");
|
final XmlElement myElement = new XmlElement("NodeName");
|
||||||
Assertions.assertEquals(myElement.getType(), NodeType.ELEMENT);
|
Assertions.assertEquals(myElement.getType(), XmlNodeType.ELEMENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void createAssignement() {
|
public void createAssignement() {
|
||||||
final Element myElement = new Element("NodeName");
|
final XmlElement myElement = new XmlElement("NodeName");
|
||||||
try {
|
try {
|
||||||
final Element myOtherElement = myElement.clone();
|
final XmlElement myOtherElement = myElement.clone();
|
||||||
Assertions.assertEquals(myElement.getValue(), myOtherElement.getValue());
|
Assertions.assertEquals(myElement.getValue(), myOtherElement.getValue());
|
||||||
} catch (final CloneNotSupportedException e) {
|
} catch (final CloneNotSupportedException e) {
|
||||||
Assertions.fail("Should Not have thrown an exception");
|
Assertions.fail("Should Not have thrown an exception");
|
||||||
@ -69,9 +69,9 @@ public class ExmlTestElement {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void createCopy() {
|
public void createCopy() {
|
||||||
final Element myElement = new Element("NodeName");
|
final XmlElement myElement = new XmlElement("NodeName");
|
||||||
try {
|
try {
|
||||||
final Element myOtherElement = new Element(myElement);
|
final XmlElement myOtherElement = new XmlElement(myElement);
|
||||||
Assertions.assertEquals(myElement.getValue(), myOtherElement.getValue());
|
Assertions.assertEquals(myElement.getValue(), myOtherElement.getValue());
|
||||||
} catch (final CloneNotSupportedException e) {
|
} catch (final CloneNotSupportedException e) {
|
||||||
Assertions.fail("Should Not have thrown an exception");
|
Assertions.fail("Should Not have thrown an exception");
|
||||||
@ -81,34 +81,34 @@ public class ExmlTestElement {
|
|||||||
@Test
|
@Test
|
||||||
public void getNamed() {
|
public void getNamed() {
|
||||||
|
|
||||||
final Element myElement = new Element("NodeName");
|
final XmlElement myElement = new XmlElement("NodeName");
|
||||||
Assertions.assertEquals(myElement.existNode("jkjhkjhkh"), false);
|
Assertions.assertEquals(myElement.existNode("jkjhkjhkh"), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getNodeId() {
|
public void getNodeId() {
|
||||||
final Element myElement = new Element("NodeName");
|
final XmlElement myElement = new XmlElement("NodeName");
|
||||||
Assertions.assertEquals(false, myElement.existNode(465));
|
Assertions.assertEquals(false, myElement.existNode(465));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getText1() {
|
public void getText1() {
|
||||||
|
|
||||||
final Element myElement = new Element("NodeName");
|
final XmlElement myElement = new XmlElement("NodeName");
|
||||||
Assertions.assertEquals("", myElement.getText());
|
Assertions.assertEquals("", myElement.getText());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getText2() {
|
public void getText2() {
|
||||||
|
|
||||||
final Element myElement = new Element("NodeName");
|
final XmlElement myElement = new XmlElement("NodeName");
|
||||||
myElement.append(new Element("jkjhkjhkh"));
|
myElement.append(new XmlElement("jkjhkjhkh"));
|
||||||
Assertions.assertEquals("<jkjhkjhkh/>\n", myElement.getText());
|
Assertions.assertEquals("<jkjhkjhkh/>\n", myElement.getText());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getTypeId() {
|
public void getTypeId() {
|
||||||
final Element myElement = new Element("NodeName");
|
final XmlElement myElement = new XmlElement("NodeName");
|
||||||
Assertions.assertThrows(ExmlNodeDoesNotExist.class, () -> myElement.getType(1));
|
Assertions.assertThrows(ExmlNodeDoesNotExist.class, () -> myElement.getType(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,8 +116,8 @@ public class ExmlTestElement {
|
|||||||
public void moveInAllElement() {
|
public void moveInAllElement() {
|
||||||
final Document doc = new Document();
|
final Document doc = new Document();
|
||||||
doc.parse("<elem><elem1/><elem2/></elem>");
|
doc.parse("<elem><elem1/><elem2/></elem>");
|
||||||
for (final Node it : doc.getNodes()) {
|
for (final XmlNode it : doc.getNodes()) {
|
||||||
final Element elem = (Element) it;
|
final XmlElement elem = (XmlElement) it;
|
||||||
Assertions.assertEquals("elem", elem.getValue());
|
Assertions.assertEquals("elem", elem.getValue());
|
||||||
Assertions.assertEquals(2, elem.getNodes().size());
|
Assertions.assertEquals(2, elem.getNodes().size());
|
||||||
Assertions.assertEquals(2, elem.size());
|
Assertions.assertEquals(2, elem.size());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user