package com.googlecode.totallylazy.xml.streaming; import com.googlecode.totallylazy.Computation; import com.googlecode.totallylazy.LazyException; import com.googlecode.totallylazy.predicates.Predicate; import com.googlecode.totallylazy.Sequence; import com.googlecode.totallylazy.Unchecked; import org.w3c.dom.Node; import javax.xml.stream.XMLEventReader; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.events.XMLEvent; import java.io.Reader; import java.io.StringReader; import java.util.Iterator; import static com.googlecode.totallylazy.LazyException.lazyException; import static com.googlecode.totallylazy.xml.streaming.XPath.descendant; import static com.googlecode.totallylazy.xml.streaming.XPath.name; import static com.googlecode.totallylazy.xml.streaming.XPath.xpath; public class Xml { private static XMLEventReader xmlEventReader(Reader reader) { try { XMLInputFactory factory = XMLInputFactory.newInstance(); factory.setProperty(XMLInputFactory.IS_COALESCING, true); factory.setProperty(XMLInputFactory.IS_VALIDATING, false); factory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, true); // so we can ignore them! factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, false); factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false); factory.setProperty(XMLInputFactory.SUPPORT_DTD, false); return factory.createXMLEventReader(reader); } catch (XMLStreamException e) { throw lazyException(e); } } public static Sequence<Node> nodes(Reader reader, String localName) throws LazyException { return nodes(reader, xpath(descendant(name(localName)))); } public static Sequence<Node> nodes(Reader reader, Predicate<Context> predicate) { return contexts(reader).filter(predicate).map(DomConverter::convert); } public static Sequence<XMLEvent> events(Reader reader) { return Computation.memoize(Unchecked.<Iterator<XMLEvent>>cast(xmlEventReader(reader))); } public static Sequence<Context> contexts(String xml) { return contexts(new StringReader(xml)); } public static Sequence<Context> contexts(Reader reader) { return contexts(new Context(events(reader)).next().get()); } public static Computation<Context> contexts(Context context) { return Computation.compute(context, Context::next); } }