[XML-DEV Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message] An XML API using Java streams
I'm struck how 95% of Java/XML users still seem to be stuck on DOM navigation, perhaps with a bit of XPath thrown in, which all seems a terribly late-20th-century way of doing things. The success of jQuery in the Javascript world, and the emergence of the Java Streams API, suggests there ought to be a better way. I don't know if anyone has done this before, but I thought I'd sketch out some ideas. (I have to say me experience with the Streams API is pretty cursory, to coin a phrase, so there may well be better ways of doing things that I've missed. In particular: (a) It would be nice to navigate using functional stream-based interfaces rather than procedural step-by-step navigation (b) It would be nice to do all the navigation using Java primitives without requiring XPath as a separate interpreted sub-language. Navigation is basically a question of constructing streams of nodes. Let's start by defining the XPath axes as functions (Node -> Stream(Node)). For example, given a node N, Axis.child(N) returns a stream containing the children of N. If we define Node.walk(F) as returning a stream that navigates using the supplied function F, then N.walk(Axis::child) gets the children of N (you could write Axis.child(N) if you prefer), while N.walk(Axis::child).flatMap(Axis::child) gets the grandchildren. If we define NodeTest::isElement as a function that returns true if the argument is an element node, then N.walk(Axis::child).filter(NodeTest::isElement) returns a stream of child nodes that are elements. If we want to match nodes with a specific local name, then NodeTest.withLocalName(String) returns a function that returns true for nodes having that local name, so we can write N.walk(Axis::child).filter(NodeTest.withLocalName("city")) This is getting a bit long-winded for a simple task, so perhaps Axis.child(N) should return a function that navigates the child axis and filters by name, so the above becomes N.walk(Axis.child("city")) If Node.stringValue() returns the string value of a node N.walk(Axis.child("city")).flatMap(Axis.attribute("name").map(Node::stringValue) returns the names of the child cities (as a Stream<String>). Perhaps there's a shortcut for this: N.walk(Axis.child("city")).map(Axis.attValue("name")) And then we could add tree construction using function chaining, e.g. element("cities") .addChild(element("city").addAttribute("name", "Rome")) .addChild(element("city").addAttribute("name", "Paris")) ===== Just an initial sketch of some ideas. Does it seem worth pursuing? Michael Kay Saxonica
[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index] |
PURCHASE STYLUS STUDIO ONLINE TODAY!Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced! Download The World's Best XML IDE!Accelerate XML development with our award-winning XML IDE - Download a free trial today! Subscribe in XML format
|