Hi,

I have a program that generates an outputstream with XML-data. With a socket connection, I have to read multiple XML-files from the inputstream.

To read only one XML-file from the inputstream is not a problem, the fact that there are more than one and I have to split up the stream somewhere poses a problem for me.

I have been looking all over the internet for a solution, but I haven't found it yet. Hopefully you can help me..

I already obtained the inputstream here.. but now I have to split it up somewhere to read the multiple files from the stream...

public void run()
	{
		try{
		    	
			InputStream is = client.getInputStream();
			parse(is);
			
			//System out the data.
			/*InputStreamReader isr = new InputStreamReader(is);
			BufferedReader br = new BufferedReader(isr);
			String line;
			line = br.readLine();
			
			while ((line = br.readLine()) != null) {
			line.trim();
			
			System.out.println(line);
			}*/
		    	
			is.close(); 
		    client.close();

		     }
	catch (IOException ioe){
		System.err.println(ioe);
	}

}

Here I want to make the document..

public static void parse(InputStream xml)
{
 try {
	  //File file = new File("c:\\output.xml");
	  DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
	  DocumentBuilder db = dbf.newDocumentBuilder();
	  
	  byte b[] = new byte[364];
	  xml.read(b);
	  
	  ByteArrayInputStream x = new ByteArrayInputStream(b);
	  Document doc = db.parse(x);
	  
	  //System.out.println(xml.available());
	  //System.out.println(new String(b));
	  //Document doc = db.parse(x);
	  
	  /*InputSource inStream = new org.xml.sax.InputSource();
	  inStream.setCharacterStream(new StringReader(xml));*/
	  
	  /*Document doc = db.parse(xml);
	  doc.getDocumentElement().normalize();
	  //System.out.println("Root element " + doc.getDocumentElement().getNodeName());
	  NodeList nodeLst = doc.getElementsByTagName("MEASUREMENT");
	  System.out.println("WEERDATA");
	  System.out.println(" ");

	  int s = 0;

	    Node fstNode = nodeLst.item(s);
	    
	    if (fstNode.getNodeType() == Node.ELEMENT_NODE) {
	  
	           Element fstElmnt = (Element) fstNode;
	           
	           //System.out.println("STN : " + getTagValue("STN", fstElmnt));
	           
	           System.out.println("STN : " + getTagValue("STN", fstElmnt));
	           System.out.println("DATE : " + getTagValue("DATE", fstElmnt));
	           System.out.println("TIME : " + getTagValue("TIME", fstElmnt));
	           System.out.println("TEMP : " + getTagValue("TEMP", fstElmnt));
	           System.out.println("DEWP : " + getTagValue("DEWP", fstElmnt));
	           System.out.println("STP : " + getTagValue("STP", fstElmnt));
	           System.out.println("SLP : " + getTagValue("SLP", fstElmnt));
	           System.out.println("VISIB : " + getTagValue("VISIB", fstElmnt));
	           System.out.println("WDSP : " + getTagValue("WDSP", fstElmnt));
	           System.out.println("PRCP : " + getTagValue("PRCP", fstElmnt));
	           System.out.println("SNDP : " + getTagValue("SNDP", fstElmnt));
	           System.out.println("FRSHTT : " + getTagValue("FRSHTT", fstElmnt));
	           System.out.println("CLDC : " + getTagValue("CLDC", fstElmnt));
	           System.out.println("WNDDIR : " + getTagValue("WNDDIR", fstElmnt));
	    }*/
	  } catch (Exception e) {
	    System.out.println("Fout");
	  }
}

private static String getTagValue(String sTag, Element eElement) {
	NodeList nlList = eElement.getElementsByTagName(sTag).item(0).getChildNodes();
 
        Node nValue = (Node) nlList.item(0);
 
	return nValue.getNodeValue();
  }

I assume you have some way of knowing where one file and and the next begins?
If so, maybe you can wrap your input stream in a FilterInputStream that recognises the end of file and returns -1 from its read method(s) before consuming the EOF marker (whatever that may be). Your parsers can then use the filtered stream and will only see one file each time they are called.

The code below is the output of the generator. A file starts with the XML declaration, and ends with the line "</WEATHERDATA>".

But how do I make the FilterInputStream recognize the end of a file?

Stream:

<?xml version="1.0"?>
<WEATHERDATA>
	<MEASUREMENT>
		<STN>879340</STN>
		<DATE>2011-09-20</DATE>
		<TIME>17:18:13</TIME>
		<TEMP>0.5</TEMP>
		<DEWP>-4.2</DEWP>
		<STP>998.8</STP>
		<SLP></SLP>
		<VISIB>12.4</VISIB>
		<WDSP>23.5</WDSP>
		<PRCP>0.00</PRCP>
		<SNDP>0.0</SNDP>
		<FRSHTT>000000</FRSHTT>
		<CLDC>41.2</CLDC>
		<WNDDIR>166</WNDDIR>
	</MEASUREMENT>
	<MEASUREMENT>
		<STN>304390</STN>
		<DATE>2011-09-20</DATE>
		<TIME>17:18:13</TIME>
		<TEMP>0.1</TEMP>
		<DEWP>-5.7</DEWP>
		<STP>992.1</STP>
		<SLP>1016.7</SLP>
		<VISIB>39.5</VISIB>
		<WDSP>6.0</WDSP>
		<PRCP>0.00</PRCP>
		<SNDP>0.0</SNDP>
		<FRSHTT>000000</FRSHTT>
		<CLDC>16.9</CLDC>
		<WNDDIR>4</WNDDIR>
	</MEASUREMENT>
</WEATHERDATA>

--- From here another XML file ---
<?xml version="1.0"?>
<WEATHERDATA>
	<MEASUREMENT>

The idea would be to subclass FilterInputStream and implement your own read method. That should read from the underlying stream (super.read), checking it for "</WEATHERDATA>". If it doesn't see that it just passes the data on to the caller, but if it does see it it passes just to the end of that string, then pass an end-of file (return -1) on the next call. That should terminate the parser normally, so then you can loop starting another parser, which will continue to read the input via the FilterInputStream subclass, starting where the previous parser finished. When your subclass reaches the real end of file it can terminate the whole process.

Thank you for your help James,

I tried to figure it out with your suggestions, but found another solution.
Now I read one XML-file from the stream, write that to a text-file, and read that file with a DOM-parser.

OK, that makes a lot of sense.
Rather than the overheads of a file, why not spool each XML-file to a ByteArrayOutputStream then run the parser from the corresponding ByteArrayInputStream. Unless the files are many megabytes this will keep it all in memory with negligable overhead.

This question has already been answered. Start a new discussion instead.