Stax2 usage for XML streams with multiple top-level elements

I work with a lot of customers who are in love with the idea of XML but have zero clue about conformance to schemas or sensible specifications for communications protocols. As such I get a lot of wooly specs about sending messages between systems that say, "I send this, then you reply with that... oh, and we want to use XML!"

Now I like to separate out the different levels of a communications protocol such that you can use any transport to pass any content. it makes systems more testable and componentised which is a Good Thing (TM). For this reason I tend to use a message passing protocol that uses a marker for the end of message so i receive data from, say, a stream socket, buffer up the bytes until I'm passed an end-of-message byte, e.g. ETX, then I pass the entire buffer off to the next stage in the system to decode and react to the message.

What I don't like doing is mixing up different layers of protocol so that you have to decode the message in order to discover the extent of the message. So when I get a spec that says we just pass XML back and forth I start to worry. I tend to argue the toss about following a standard such as XMMP (http://en.wikipedia.org/wiki/XMPP) and mention that the data being passed isn't even well-formed since XML allows only a single top-level element (XMPP uses a wrapper element for the entire conversation).

Well, I'm in that position right now: I have a pretty clueless company who've defined a shoddy protocol and I have to comply. I ain't gonna write my own fatally flawed angle-bracket counting algorithm like they have ("Does it cope with CDATA sections?", "What's CDATA?"), I'm gonna use a StAX parser - NO! I'm gonna use a StAX2 parser!!!

The woodstox StAX2 parser allows multiple top-level elements to appear on an input stream when thus configured...


XMLInputFactory f2 = XMLInputFactory2.newInstance();
f2.setProperty("com.ctc.wstx.fragmentMode", WstxInputProperties.PARSING_MODE_FRAGMENT);
String msgsrc = "";
Reader sr2 = new StringReader(msgsrc);
try {
XMLStreamReader strmrdr = f2.createXMLStreamReader(sr2);
while(strmrdr.hasNext()){
int evt = strmrdr.next();
switch(evt){
case XMLStreamConstants.START_ELEMENT:
String localName = strmrdr.getLocalName();
log.debug("start elem:" + localName);
break;
case XMLStreamConstants.ATTRIBUTE:
break;
}
}
} catch (XMLStreamException e1) {
log.fatal("problem:", e1);
}

Dammit! why does drupal hide my tabs?

and to read any attributes...


package com.tecspy.xmlutil;

import java.util.Map;

import javax.xml.stream.XMLStreamReader;

/**
* @author Michael Erskine
*/
public class StaxUtils {
/**
* Adds attribute name and value pairs to the Map. Assumes the reader is
* currently located at an element.
*
* @param reader
* @param attmap
*/
public static void staxGetAttrs(XMLStreamReader reader,
Map attmap) {
int ac = reader.getAttributeCount();
for (int i = 0; i < ac; i++) {
String name = reader.getAttributeLocalName(i);
String value = reader.getAttributeValue(i);
attmap.put(name, value);
}
}
}