This shows you how to
1. Read in an XML file to a DOM
2. Filter out a set of Nodes with XPath
3. Perform a certain action on each of the extracted Nodes.
We will call the code with the following statement
processFilteredXml(xmlIn, xpathExpr,(node) -> {/*Do something...*/;});
In our case we want to print some creatorNames from a book.xml using “//book/creators/creator/creatorName” as xpath to perform a printNode action on each Node that matches the XPath.
Full code
@Test public void printXml() { try (InputStream in = readFile("book.xml")) { processFilteredXml(in, "//book/creators/creator/creatorName", (node) -> { printNode(node, System.out); }); } catch (Exception e) { throw new RuntimeException(e); } } private InputStream readFile(String yourSampleFile) { return Thread.currentThread().getContextClassLoader().getResourceAsStream(yourSampleFile); } private void processFilteredXml(InputStream in, String xpath, Consumer<Node> process) { Document doc = readXml(in); NodeList list = filterNodesByXPath(doc, xpath); for (int i = 0; i < list.getLength(); i++) { Node node = list.item(i); process.accept(node); } } public Document readXml(InputStream xmlin) { try { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); return db.parse(xmlin); } catch (Exception e) { throw new RuntimeException(e); } } private NodeList filterNodesByXPath(Document doc, String xpathExpr) { try { XPathFactory xPathFactory = XPathFactory.newInstance(); XPath xpath = xPathFactory.newXPath(); XPathExpression expr = xpath.compile(xpathExpr); Object eval = expr.evaluate(doc, XPathConstants.NODESET); return (NodeList) eval; } catch (Exception e) { throw new RuntimeException(e); } } private void printNode(Node node, PrintStream out) { try { Transformer transformer = TransformerFactory.newInstance().newTransformer(); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); StreamResult result = new StreamResult(new StringWriter()); DOMSource source = new DOMSource(node); transformer.transform(source, result); String xmlString = result.getWriter().toString(); out.println(xmlString); } catch (Exception e) { throw new RuntimeException(e); } }
Prints
<creatorName>Fosmire, Michael</creatorName> <creatorName>Wertz, Ruth</creatorName> <creatorName>Purzer, Senay</creatorName>
For book.xml
<book> <creators> <creator> <creatorName>Fosmire, Michael</creatorName> <givenName>Michael</givenName> <familyName>Fosmire</familyName> </creator> <creator> <creatorName>Wertz, Ruth</creatorName> <givenName>Ruth</givenName> <familyName>Wertz</familyName> </creator> <creator> <creatorName>Purzer, Senay</creatorName> <givenName>Senay</givenName> <familyName>Purzer</familyName> </creator> </creators> <titles> <title>Critical Engineering Literacy Test (CELT)</title> </titles> </book>
See also
https://stackoverflow.com/a/52736526/1485527
https://github.com/jschnasse/overflow/tree/master/src/test/java/stack52720162