This page was generated using Webiyo. See its source code and unit tests.
|
org/webiyo/xml/Xml.javapackage org.webiyo.xml; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.*; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import java.io.*; import java.util.ArrayList; import java.util.Formatter; import java.util.List; public class Xml { private static final String STRING_SYSTEM_ID = "<xml from string>"; private Xml() { } public static Document parse(InputSource inputSource) throws IOException { Document result; try { result = newXmlParser(false, null).parse(inputSource); } catch (SAXException e) { throw new XmlException(e.getMessage(), e); } return result; } public static Document parse(String xml) throws IOException { InputSource source = new InputSource(new StringReader(xml)); source.setSystemId(STRING_SYSTEM_ID); Document result; try { result = newXmlParser(false, null).parse(source); } catch (SAXParseException e) { String message = makeMessageWithSnippet(e, xml); throw new XmlException(message, e); } catch (SAXException e) { throw new XmlException(e.getMessage(), e); } return result; } public static Document parseAndValidate(String xml, EntityResolver resolver) throws SAXException, IOException { InputSource source = new InputSource(new StringReader(xml)); source.setSystemId(STRING_SYSTEM_ID); Document result; try { result = newXmlParser(true, resolver).parse(source); } catch (SAXParseException e) { String message = makeMessageWithSnippet(e, xml); throw new XmlException(message, e); } return result; } public static Element selectElement(Element itemElt, String xpath) throws XmlException { return selectOne(itemElt, xpath, Element.class); } public static <T> T selectOne(Element element, String xpath, Class<T> expectedNodeClass) throws XmlException { List<T> nodes = select(element, xpath, expectedNodeClass); if (nodes.size() < 1) { throw new XmlException("no match found for xpath \"" + xpath + "\"", null); } else if (nodes.size() > 1) { throw new XmlException("found " + nodes.size() + " matches for xpath \"" + xpath + "\"", null); } return nodes.get(0); } public static <T> List<T> select(Element element, String xpath, Class<T> expectedNodeClass) throws XmlException { try { XPath xp = XPathFactory.newInstance().newXPath(); NodeList nodes = (NodeList) xp.evaluate(xpath, element, XPathConstants.NODESET); return toList(nodes, expectedNodeClass); } catch (XPathExpressionException e) { throw new XmlException("error in xpath \"" + xpath + "\"", e); } } public static <T> List<T> toList(NodeList nodes, Class<T> expectedNodeClass) { List<T> result = new ArrayList<T>(); for (int i = 0; i < nodes.getLength(); i++) { Node node = nodes.item(i); result.add(expectedNodeClass.cast(node)); } return result; } public static AttributeSource att(final AttributeType attType, final String value) { return new AttributeSource() { public void sendAttributes(AttributeSink sink) throws IOException { sink.putAttribute(attType.getName(), value); } }; } // end of public methods private static DocumentBuilder newXmlParser(boolean validating, EntityResolver resolver) throws XmlException { try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setValidating(validating); DocumentBuilder builder = factory.newDocumentBuilder(); if (resolver != null) { builder.setEntityResolver(resolver); } builder.setErrorHandler(new SaxErrorHandler()); return builder; } catch (ParserConfigurationException e) { throw new XmlException("unable to create XML parser", e); } } private static String makeMessageWithSnippet(SAXParseException original, String xml) { int wantedLineNumber = original.getLineNumber(); if (wantedLineNumber < 1) { return original.getMessage(); } try { LineNumberReader reader = makeLineNumberReader(original, xml); String lines = extractSnippet(reader, wantedLineNumber); return original.getMessage() + "\n" + "error on line " + original.getLineNumber() + ":\n" + lines; } catch (IOException e) { return null; } } private static LineNumberReader makeLineNumberReader(SAXParseException original, String xml) throws FileNotFoundException { if (STRING_SYSTEM_ID.equals(original.getSystemId())) { return new LineNumberReader(new StringReader(xml)); } else { return new LineNumberReader(new FileReader(new File(original.getSystemId()))); } } private static String extractSnippet(LineNumberReader reader, int wantedLineNumber) throws IOException { // skip lines above snippet while (reader.getLineNumber() < wantedLineNumber - 2) { String line = reader.readLine(); if (line == null) return ""; } StringBuilder result = new StringBuilder(); while (reader.getLineNumber() < wantedLineNumber + 2) { String line = reader.readLine(); if (line == null) break; new Formatter(result).format("% 4d: %s\n", reader.getLineNumber(), line); } return result.toString(); } // inner classes static class SaxErrorHandler implements ErrorHandler { public void warning(SAXParseException exception) throws SAXException { throw exception; } public void error(SAXParseException exception) throws SAXException { throw exception; } public void fatalError(SAXParseException exception) throws SAXException { throw exception; } } } |