package shared.dataInput; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.xml.sax.SAXException; import shared.exceptions.XMLReaderException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import java.io.IOException; import java.io.InputStream; import java.io.StringWriter; /** * Base Reader for XML Files */ public abstract class XMLReader { protected Document doc; /** * Read an XML file by name as a resource. * @param filePath filepath for XML file. Loaded as a resource. * @throws XMLReaderException Thrown if the file cannot be parsed. */ public XMLReader(String filePath) throws XMLReaderException { //Read file as resource. InputStream xmlInputStream = getClass().getClassLoader().getResourceAsStream(filePath); this.doc = parseInputStream(xmlInputStream); } /** * Reads an XML file from an input stream. * @param xmlInputStream The input stream to parse. * @throws XMLReaderException Thrown if the input stream cannot be parsed. */ public XMLReader(InputStream xmlInputStream) throws XMLReaderException { this.doc = parseInputStream(xmlInputStream); } /** * Parses an input stream into a document. * @param inputStream The xml input stream to parse. * @return The parsed document. * @throws XMLReaderException Thrown when a document builder cannot be constructed, or the stream cannot be parsed. */ private Document parseInputStream(InputStream inputStream) throws XMLReaderException { //Create document builder. DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder dBuilder = null; try { dBuilder = dbFactory.newDocumentBuilder(); } catch (ParserConfigurationException e) { throw new XMLReaderException("Could not create a DocumentBuilder.", e); } //Parse document. Document document = null; try { document = dBuilder.parse(inputStream); } catch (SAXException | IOException e) { throw new XMLReaderException("Could not parse the xml input stream.", e); } document.getDocumentElement().normalize(); return document; } /** * Return Document data of the read-in XML * @return XML document */ public Document getDocument() { return doc; } /** * Get content of a tag in an element * @param n Element to read tags from * @param tagName Name of the tag * @return Content of the tag */ public String getTextValueOfNode(Element n, String tagName) { return n.getElementsByTagName(tagName).item(0).getTextContent(); } /** * Get attributes for an element * @param n Element to read attributes from * @param attr Attributes of element * @return Attributes of element */ public String getAttribute(Element n, String attr) { return n.getAttribute(attr); } protected boolean exists(Node node, String attribute) { return node.getAttributes().getNamedItem(attribute) != null; } /** * Get the contents of the XML FILe. * @param document holds all xml information * @return String representation of document * @throws TransformerException when document is malformed, and cannot be turned into a string */ public static String getContents(Document document) throws TransformerException { DOMSource source = new DOMSource(document); TransformerFactory transformerFactory = TransformerFactory.newInstance(); Transformer transformer = transformerFactory.newTransformer(); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); StringWriter stringWriter = new StringWriter(); StreamResult result = new StreamResult(stringWriter); transformer.transform(source, result); return stringWriter.toString(); } }