package rene.util.xml; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import rene.util.SimpleByteBuffer; import rene.util.SimpleStringBuffer; import rene.util.list.ListElement; public class XmlReader { BufferedReader In; SimpleStringBuffer buf=new SimpleStringBuffer(10000); public XmlReader () { In=null; } public XmlReader (BufferedReader in) { In=in; } public XmlReader (InputStream in) throws XmlReaderException { try { // read the file into a buffer BufferedInputStream rin=new BufferedInputStream(in); SimpleByteBuffer bb=new SimpleByteBuffer(10000); while (true) { int k=rin.read(); if (k<0) break; bb.append((byte)k); } rin.close(); byte b[]=bb.getByteArray(); // Try to open an ASCII stream, or a default stream ByteArrayInputStream bin=new ByteArrayInputStream(b); XmlReader R=null; try { R=new XmlReader(new BufferedReader(new InputStreamReader(bin,"ASCII"))); } catch (UnsupportedEncodingException ex) { R=new XmlReader(new BufferedReader(new InputStreamReader(bin))); } // Determine the encoding String Encoding=null; while (true) { while (true) { int c=R.read(); if (c==-1) throw new Exception("<?xml> tag not found"); if (c=='<') break; } if (R.found("?xml")) { String s=R.scanFor("?>"); if (s==null) throw new Exception("<?xml> tag error"); int n=s.indexOf("encoding=\""); if (n>=0) { n+="encoding=\"".length(); s=s.substring(n); int m=s.indexOf('\"'); if (m<0) throw new Exception("Closing bracket missing"); Encoding=s.substring(0,m).toUpperCase(); if (Encoding.equals("UTF-8")) Encoding="UTF8"; // for IE5 ! break; } break; } } // Open a stream with this encoding bin=new ByteArrayInputStream(b); if (Encoding==null) In=new BufferedReader(new InputStreamReader(bin)); else try { In=new BufferedReader(new InputStreamReader( bin,Encoding)); } catch (UnsupportedEncodingException e) { try { In=new BufferedReader(new InputStreamReader( bin,"ASCII")); } catch (UnsupportedEncodingException ex) { In=new BufferedReader(new InputStreamReader(bin)); } } } catch (Exception e) { throw new XmlReaderException(e.toString()); } } public void init (InputStream in) throws XmlReaderException { try { // read the file into a buffer BufferedInputStream rin=new BufferedInputStream(in); SimpleByteBuffer bb=new SimpleByteBuffer(10000); while (true) { int k=rin.read(); if (k<0) break; bb.append((byte)k); } rin.close(); byte b[]=bb.getByteArray(); // Try to open an ASCII stream, or a default stream ByteArrayInputStream bin=new ByteArrayInputStream(b); XmlReader R=null; try { R=new XmlReader(new BufferedReader(new InputStreamReader(bin,"ASCII"))); } catch (UnsupportedEncodingException ex) { R=new XmlReader(new BufferedReader(new InputStreamReader(bin))); } // Determine the encoding String Encoding=null; while (true) { while (true) { int c=R.read(); if (c==-1) throw new Exception("<?xml> tag not found"); if (c=='<') break; } if (R.found("?xml")) { String s=R.scanFor("?>"); if (s==null) throw new Exception("<?xml> tag error"); int n=s.indexOf("encoding=\""); if (n>=0) { n+="encoding=\"".length(); s=s.substring(n); int m=s.indexOf('\"'); if (m<0) throw new Exception("Closing bracket missing"); Encoding=s.substring(0,m).toUpperCase(); if (Encoding.equals("UTF-8")) Encoding="UTF8"; // for IE5 ! break; } break; } } // Open a stream with this encoding bin=new ByteArrayInputStream(b); if (Encoding==null) In=new BufferedReader(new InputStreamReader(bin)); else try { In=new BufferedReader(new InputStreamReader( bin,Encoding)); } catch (UnsupportedEncodingException e) { try { In=new BufferedReader(new InputStreamReader( bin,"ASCII")); } catch (UnsupportedEncodingException ex) { In=new BufferedReader(new InputStreamReader(bin)); } } } catch (Exception e) { throw new XmlReaderException(e.toString()); } } /** Scan an xml file. This function reads, until <?xml is found. then it skips this declaration and scans the rest of the items. */ public XmlTree scan () throws XmlReaderException { while (true) { while (true) { int c=read(); if (c==-1) return null; if (c=='<') break; } if (found("?xml")) { String s=scanFor("?>"); if (s==null) return null; XmlTree t=new XmlTree(new XmlTagRoot()); t.addchild(new XmlTree(new XmlTagPI(s))); scanContent(t); return t; } } } public void scanContent (XmlTree t) throws XmlReaderException { //System.out.println("Sanning for "+t.getTag().name()+" ("+ // t.getTag().countParams()+")"); while (true) { String s=scanFor('<'); if (s==null) { if (t.getTag() instanceof XmlTagRoot) return; exception("File ended surprisingly"); } if (!empty(s)) { t.addchild(new XmlTree(new XmlTagText( XmlTranslator.toText(s)))); } if (found("!--")) { s=scanFor("-->"); continue; } if (found("!")) { s=scanTagFor('>'); continue; } if (found("?")) { s=scanTagFor("?>"); t.addchild(new XmlTree(new XmlTagPI(s))); continue; } s=scanTagFor('>'); if (s==null) exception("> missing"); if (s.startsWith("/")) { if (s.substring(1).equals(t.getTag().name())) return; else exception("End tag without start tag"); } if (s.endsWith("/")) { t.addchild(new XmlTree(new XmlTag(s.substring(0,s.length()-1)))); } else { XmlTree t0=new XmlTree(new XmlTag(s)); scanContent(t0); t.addchild(t0); } } } public boolean empty (String s) { int n=s.length(); for (int i=0; i<n; i++) { char c=s.charAt(i); if (c!=' ' && c!='\n' && c!='\t') return false; } return true; } /** Skip Blanks. @return Non-blank character or -1 for EOF. */ public int skipBlanks () throws XmlReaderException { while (true) { int c=read(); if (c==' ' || c=='\t' || c=='\n') continue; else return c; } } /** Scan for an end character. @return String between the current position and the end character, or null. */ public String scanFor (char end) throws XmlReaderException { buf.clear(); int c=read(); while (c!=end) { buf.append((char)c); c=read(); if (c<0) return null; } return buf.toString(); } /** Scan for a specific string. @return String between the current position and the string. */ public String scanFor (String s) throws XmlReaderException { buf.clear(); while (!found(s)) { int c=read(); if (c<0) return null; buf.append((char)c); } for (int i=0; i<s.length(); i++) read(); return buf.toString(); } /** Scan tag for an end character (interpreting " and ') @return String between the current position and the end character, or null. */ public String scanTagFor (char end) throws XmlReaderException { buf.clear(); int c=read(); while (c!=end) { if (c=='\"') { buf.append((char)c); while (true) { c=read(); if (c<0) return null; if (c=='\"') break; buf.append((char)c); } buf.append((char)c); } else if (c=='\'') { buf.append((char)c); while (true) { c=read(); if (c<0) return null; if (c=='\'') break; buf.append((char)c); } buf.append((char)c); } else buf.append((char)c); c=read(); if (c<0) return null; } return buf.toString(); } /** Scan tag for a specific string (interpreting " and ') @return String between the current position and the string. */ public String scanTagFor (String s) throws XmlReaderException { buf.clear(); while (!found(s)) { int c=read(); if (c<0) return null; if (c=='\"') { buf.append((char)c); while (true) { c=read(); if (c<0) return null; if (c=='\"') break; buf.append((char)c); } buf.append((char)c); } else if (c=='\'') { buf.append((char)c); while (true) { c=read(); if (c<0) return null; if (c=='\'') break; buf.append((char)c); } buf.append((char)c); } else buf.append((char)c); } for (int i=0; i<s.length(); i++) read(); return buf.toString(); } String Line=null; int LinePos; public int read () throws XmlReaderException { try { if (Line==null) { Line=In.readLine(); LinePos=0; // System.out.println("Read --> "+Line); } if (Line==null) return -1; if (LinePos>=Line.length()) { Line=null; return '\n'; } return Line.charAt(LinePos++); } catch (Exception e) { return -1; } } /** @return If the string is at the current line position. */ public boolean found (String s) { int n=s.length(); if (LinePos+n>Line.length()) return false; for (int i=0; i<n; i++) if (s.charAt(i)!=Line.charAt(LinePos+i)) return false; return true; } public void exception (String s) throws XmlReaderException { throw new XmlReaderException(s,Line,LinePos); } /** A test program. */ public static void main (String args[]) { try { BufferedReader in=new BufferedReader( new InputStreamReader( new FileInputStream("rene\\util\\xml\\test.xml"),"UTF8")); XmlReader reader=new XmlReader(in); XmlTree tree=reader.scan(); in.close(); print(tree); } catch (XmlReaderException e) { System.out.println(e.toString()+"\n"+ e.getLine()+"\n"+"Position : "+e.getPos()); } catch (IOException e) { System.out.println(e); } } public static void print (XmlTree t) { XmlTag tag=t.getTag(); System.out.print("<"+tag.name()); for (int i=0; i<tag.countParams(); i++) { System.out.print(" "+tag.getParam(i)+"=\""+tag.getValue(i)+"\""); } System.out.println(">"); ListElement el=t.children().first(); while (el!=null) { print((XmlTree)(el.content())); el=el.next(); } System.out.println("</"+tag.name()+">"); } public static boolean testXml (String s) { int i=0; while (i<s.length()) { char c=s.charAt(i); if (c=='<') break; i++; } if (i>=s.length()) return false; if (s.substring(i).startsWith("<?xml")) return true; return false; } }