package ca.umontreal.iro.rali; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.PrintStream; import java.util.ArrayList; import java.util.Collections; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import javax.xml.stream.XMLStreamException; import org.w3c.dom.DOMException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import org.xml.sax.ext.DefaultHandler2; import org.xml.sax.helpers.DefaultHandler; /** * Show the XPath expressions corresponding to paths going from the root to leaves in an XML documents * using a SAX parser * * @author Guy Lapalme, Université de Montréal, 2009 * */ public class ExploreSAX { /** * To keep the count of each XPath expression */ private static SortedMap pathCounts; private static InputStream input=null; private static PrintStream out=null; // Print stream corresponding to the output /** * Set up and initialize the SAX parser and stream writer output file * * @return the number of bytes in the input file */ protected static long setInputOutput(){ long fileLength=-1; try{ // create input if(Options.inputFileName==null){ input=System.in; } else { File file=new File(Options.inputFileName); fileLength=file.length(); input=new FileInputStream(file); } // create output if(Options.outputFileName==null) out=System.out; else out=new PrintStream(Options.outputFileName); } catch (FileNotFoundException e){ e.printStackTrace(); } return fileLength; } /////////////////////////////////////////////////////////////////////////////////////////////////// // Xplore part when no -xp arg is given // /** * Explore an XML file by generating a series of Path expression describing leafs of the skeleton * document; called when no -xp argument is given * * @throws DOMException * @throws XMLStreamException * @throws ParserConfigurationException */ static protected long execute(){ // read the file and create a spine document if(Options.sortAlpha || Options.sortFreq) pathCounts = new TreeMap(); long fileLength=setInputOutput(); //XMLParser creation try{ SAXParserFactory factory; SAXParser saxParser; factory = SAXParserFactory.newInstance(); factory.setNamespaceAware(true); saxParser = factory.newSAXParser(); DefaultHandler h = new ExploreSAXHandler(out,pathCounts); saxParser.setProperty("http://xml.org/sax/properties/lexical-handler", h); // to receive comment events... saxParser.parse(input,h); } catch (ParserConfigurationException e) { System.err.println("Bad parser configuration"); e.printStackTrace(); } catch (SAXParseException e) { System.err.println(Options.inputFileName+" is not well-formed"); System.err.println(e.getMessage()+ " at line "+e.getLineNumber()+ ", column "+e.getColumnNumber()); e.printStackTrace(); } catch (SAXException e){ System.err.println(e.getMessage()); e.printStackTrace(); } catch (IOException e){ e.printStackTrace(); } // output namespace prefixes if(Options.showNamespaces){ out.print(Options.nsContext); } // output statistics if(Options.sortFreq || Options.sortAlpha){ String fmt="%10d:%s\n"; if(Options.sortFreq){ ArrayList freqs = new ArrayList(pathCounts.values()); Collections.sort(freqs, PathCount.decVal); for(PathCount c:freqs) out.format(fmt,c.getVal(),c.getPath()); } else if (Options.sortAlpha) { for(Map.Entry e :pathCounts.entrySet()) out.format(fmt,e.getValue().getVal(),e.getValue().getPath()); } } return fileLength; } }