package jeql.command.io.xml;
import java.io.Reader;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import jeql.command.io.NameStack;
import com.ctc.wstx.stax.WstxInputFactory;
public class XMLStackReader
{
private XMLStreamReader rdr;
private NameStack pathStk;
private String value;
private Object prevStart;
private String prevAttr;
private boolean includeAllEndElements;
private Atom atomBuffer = null;
public XMLStackReader(Reader inRdr, boolean includeAllEndElements)
throws Exception
{
WstxInputFactory fact = new WstxInputFactory();
this.rdr = fact.createXMLStreamReader(inRdr);
//model = new DocumentModel();
pathStk = new NameStack("/");
this.includeAllEndElements = includeAllEndElements;
}
/**
* Returns next XML Atom
* @return
* @throws XMLStreamException
*/
public Atom next()
throws XMLStreamException
{
if (rdr == null) return null;
//String name = null;
//prevStart = null;
/*
if (endPath != null) {
String save = endPath;
endPath = null;
return new Atom("/" + save);
}
*/
while (rdr.hasNext()) {
if (atomBuffer != null) {
Atom atom = atomBuffer;
atomBuffer = null;
return atom;
}
int event = rdr.getEventType();
//System.out.println(event);
if (event == XMLStreamConstants.START_ELEMENT) {
String name = rdr.getLocalName();
String attr = XMLParseUtil.readAttributes(rdr);
boolean isNewElement = prevStart != null && ! name.equals(prevStart);
Atom atom = null;
if (isNewElement) {
atom = new Atom(pathStk.getNameList(), prevAttr, null);
}
prevStart = name;
prevAttr = attr;
value = null;
pathStk.push(name);
rdr.next();
if (atom != null) return atom;
}
else if (event == XMLStreamConstants.CHARACTERS) {
value = rdr.getText();
rdr.next();
continue;
}
else if (event == XMLStreamConstants.END_ELEMENT) {
String name = rdr.getLocalName();
// System.out.println("/" + locName);
// value = "***" + locName;
String startPath = pathStk.getNameList();
pathStk.pop();
rdr.next();
boolean isLeaf = name.equals(prevStart);
//Atom leaf = null;
if (isLeaf) {
prevStart = null;
// can return value now
Atom leaf = new Atom(startPath, prevAttr, value);
if (includeAllEndElements) {
Atom endElt = new Atom("/" + startPath, null, null);
atomBuffer = endElt;
}
return leaf;
}
// end element for non-leaf
Atom endElt = new Atom("/" + startPath, null, null);
return endElt;
}
else if (event == XMLStreamConstants.END_DOCUMENT) {
rdr.close();
rdr = null;
return null;
}
else {
rdr.next();
}
}
return null;
}
public void close()
{
try {
rdr.close();
}
catch (XMLStreamException e) {
}
}
public static class Atom
{
String path;
String attr;
String value;
public Atom(String path) {
this(path, "", null);
}
public Atom(String path, String attr, String value)
{
this.path = path;
this.attr = attr;
this.value = value;
}
}
}