Java tutorial
/** * Copyright (c)2012, Rational Developers; Ryan McGuinness * All rights reserved * Site: http://www.rationaldevelopers.com/fulcrum-xml * License: http://www.rationaldevelopers.com/fulcrum-xml/license.txt * Read Me: http://www.rationaldevelopers.com/fulcrum-xml/readme.txt *. */ package fulcrum.xml; import static fulcrum.xml.XMLConstants.AT; import static fulcrum.xml.XMLConstants.FORWARD_SLASH; import static fulcrum.xml.XMLConstants.REGEX_SPACE; import static fulcrum.xml.XMLConstants.SPACE; import java.io.ByteArrayInputStream; import java.io.File; import java.io.InputStream; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Stack; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.apache.commons.vfs2.FileContent; import org.apache.commons.vfs2.FileObject; import org.apache.commons.vfs2.FileSystemManager; import org.apache.commons.vfs2.VFS; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; /** * * @author Rational Developers * @author Ryan McGuinness * * This is the default parser for XML streams. Currently using SAX but * may offer a pull parser later. Currently the parser is tightly * coupled with the Document object that uses it. * */ public class Parser extends DefaultHandler { private static final Logger LOGGER = LoggerFactory.getLogger(Parser.class); public static final String ERR_01 = "Invalid file name passed to document parser: "; private static final SAXParserFactory SAX_PARSE_FACTORY = SAXParserFactory.newInstance(); private static FileSystemManager fsManager; static { SAX_PARSE_FACTORY.setValidating(true); SAX_PARSE_FACTORY.setNamespaceAware(true); SAX_PARSE_FACTORY.setXIncludeAware(true); try { fsManager = VFS.getManager(); } catch (Exception e) { e.printStackTrace(); } } private Set<Namespace> namespaces = new HashSet<Namespace>(); private Stack<Element> elements = new Stack<Element>(); private StringBuilder xPathBuilder = new StringBuilder(); private StringBuilder textBuilder = new StringBuilder(); private Document document = null; private void addXPath(String path, Node e) { Map<String, List<Node>> xPathMap = document.getxPathMap(); if (xPathMap != null) { if (xPathMap.containsKey(path)) { xPathMap.get(path).add(e); } else { List<Node> lElements = new ArrayList<Node>(); lElements.add(e); xPathMap.put(path, lElements); } } } private static SAXParser getParser() throws ParserConfigurationException, SAXException { return SAX_PARSE_FACTORY.newSAXParser(); } /** * Only provides parsing functions to the "fulcrum.xml" package. * * @see Document * * @param fileLocation * @param document * @throws ParseException */ protected void parse(String fileLocation, Document document) throws ParseException { FileObject fileObj = null; try { fileObj = fsManager.resolveFile(fileLocation); if (fileObj != null && fileObj.exists() && fileObj.isReadable()) { FileContent content = fileObj.getContent(); InputStream is = content.getInputStream(); int size = is.available(); LOGGER.debug("Total File Size: " + size + " bytes"); byte[] buffer = new byte[size]; is.read(buffer, 0, size); LOGGER.debug("Start parsing"); parse(buffer, document); LOGGER.debug("Finished paring"); buffer = null; content.close(); fileObj.close(); } } catch (Exception e) { throw new ParseException(e); } } /** * * Only provides parsing functions to the "fulcrum.xml" package. * * @see Document * * @param xmlDocument * @param document * @throws ParseException */ protected void parse(byte[] xmlDocument, Document document) throws ParseException { try { this.document = document; SAXParser sp = getParser(); ByteArrayInputStream bais = new ByteArrayInputStream(xmlDocument); sp.parse(bais, this); } catch (Exception e) { throw new ParseException(e); } } /** * * Only provides parsing functions to the "fulcrum.xml" package. * * @see Document * * @param f * @param document * @throws ParseException */ protected void parse(File f, Document document) throws ParseException { this.document = document; try { SAXParser sp = getParser(); sp.parse(f, this); } catch (Exception e) { throw new ParseException(e); } } @Override public void startPrefixMapping(String prefix, String uri) throws SAXException { Namespace ns = new Namespace(prefix, uri); if (!namespaces.contains(ns)) { namespaces.add(ns); } } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { textBuilder.setLength(0); Element c = new Element(qName, uri); xPathBuilder.append(FORWARD_SLASH).append(localName); addXPath(xPathBuilder.toString(), c); for (int i = 0; i < attributes.getLength(); i++) { Attribute a = new Attribute(attributes.getQName(i), attributes.getURI(i), attributes.getValue(i)); addXPath(xPathBuilder.toString() + AT + a.getLocalName(), a); c.addAttribute(a); } elements.push(c); } @Override public void characters(char[] c, int start, int end) throws SAXException { textBuilder.append(c, start, end); } @Override public void endElement(String uri, String localName, String qName) throws SAXException { if (elements.size() != 1) { Element c = elements.pop(); if (textBuilder != null && textBuilder.length() > 0) { String v = textBuilder.toString(); c.setText(v.replaceAll(REGEX_SPACE, SPACE).trim()); textBuilder.setLength(0); } xPathBuilder.setLength(xPathBuilder.lastIndexOf(FORWARD_SLASH)); elements.peek().addElement(c); } } @Override public void endDocument() throws SAXException { super.endDocument(); Element root = elements.firstElement(); document.setRoot(root); this.elements = null; this.namespaces = null; this.xPathBuilder = null; this.textBuilder = null; } }