* PIs and comments outside of root node), we must start with
* START_DOCUMENT event.
*/
boolean wholeDoc = (r.getEventType() == XMLStreamConstants.START_DOCUMENT);
XMLStreamReader2 sr = Stax2ReaderAdapter.wrapIfNecessary(r);
QNameRecycler recycler = new QNameRecycler();
boolean nsAware = _isNamespaceAware(sr);
Node current = doc; // At top level
main_loop:
for (int evtType = sr.getEventType(); true; evtType = sr.next()) {
Node child;
switch (evtType) {
case XMLStreamConstants.CDATA:
child = doc.createCDATASection(sr.getText());
break;
case XMLStreamConstants.SPACE:
if (_inputCfgIgnoreWs) {
continue main_loop;
}
/* Oh great. DOM is brain-dead in that ignorable white space
* can not be added, even though it is legal, and often
* reported by StAX/SAX impls...
*/
if (current == doc) { // better just ignore, thus...
continue;
}
// fall through
case XMLStreamConstants.CHARACTERS:
child = doc.createTextNode(sr.getText());
break;
case XMLStreamConstants.COMMENT:
child = doc.createComment(sr.getText());
break;
case XMLStreamConstants.END_DOCUMENT:
break main_loop;
case XMLStreamConstants.END_ELEMENT:
current = current.getParentNode();
if (current == null || current == doc) {
/* 19-Nov-2010, tatu: If the root element closed, we now need
* to bail out UNLESS we are building "whole document"
* (in which case still need to get possible PIs, comments)
*/
if (!wholeDoc) {
break main_loop;
}
}
continue main_loop;
case XMLStreamConstants.ENTITY_DECLARATION:
case XMLStreamConstants.NOTATION_DECLARATION:
/* Shouldn't really get these, but maybe some stream readers
* do provide the info. If so, better ignore it -- DTD event
* should have most/all we need.
*/
continue main_loop;
case XMLStreamConstants.ENTITY_REFERENCE:
child = doc.createEntityReference(sr.getLocalName());
break;
case XMLStreamConstants.PROCESSING_INSTRUCTION:
child = doc.createProcessingInstruction(sr.getPITarget(), sr.getPIData());
break;
case XMLStreamConstants.START_ELEMENT:
// Ok, need to add a new element...
{
String ln = sr.getLocalName();
Element newElem;
if (nsAware) {
String qname = sr.getPrefixedName();
newElem = doc.createElementNS(sr.getNamespaceURI(), qname);
} else { // if non-ns-aware, things are simpler:
newElem = doc.createElement(ln);
}
/* Silly old DOM: must mix in namespace declarations
* in there...
*/
for (int i = 0, len = sr.getNamespaceCount(); i < len; ++i) {
String prefix = sr.getNamespacePrefix(i);
String qname;
if (prefix == null || prefix.length() == 0) {
qname = "xmlns";
} else {
qname = recycler.getQualified("xmlns", prefix);
}
newElem.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, qname, sr.getNamespaceURI(i));
}
// And then the attributes:
for (int i = 0, len = sr.getAttributeCount(); i < len; ++i) {
ln = sr.getAttributeLocalName(i);
if (nsAware) {
String prefix = sr.getAttributePrefix(i);
if (prefix != null && prefix.length() > 0) {
ln = recycler.getQualified(prefix, ln);
}
newElem.setAttributeNS(sr.getAttributeNamespace(i), ln, sr.getAttributeValue(i));
} else {
newElem.setAttribute(ln, sr.getAttributeValue(i));
}
}
// And then 'push' new element...
current.appendChild(newElem);
current = newElem;
continue main_loop;
}
case XMLStreamConstants.START_DOCUMENT:
/* This should only be received at the beginning of document...
* so, should we indicate the problem or not?
*/
/* For now, let it pass: maybe some (broken) readers pass
* that info as first event in beginning of doc?
*/
continue main_loop;
case XMLStreamConstants.DTD:
/* !!! Note: StAX does not expose enough information about
* doctype declaration (specifically, public and system id!);
* (altough StAX2 would...)
*
* Worse, DOM1/2 do not specify a way to create the DocType
* node, even if StAX provided it. This is pretty silly,
* all in all.
*/
continue main_loop;
// Should never get these, from a stream reader:
/* (commented out entries are just FYI; default catches
* them all)
*/
//case XMLStreamConstants.ATTRIBUTE:
//case XMLStreamConstants.NAMESPACE:
default:
throw new XMLStreamException("Unrecognized iterator event type: "+sr.getEventType()+"; should not receive such types (broken stream reader?)");
}
if (child != null) {
current.appendChild(child);
}