How to count the depth of XML document (DOM Parser)
In the DOM parser, we can use a recursive loop of the child nodes to find or count the depth of the XML document.
Table of contents
- 1. An XML file
- 2. DOM Parser + Recursive Loop
- 3. DOM Parser + Tree Walker
- 4. Download Source Code
- 5. References
P.S Tested with Java 11.
1. An XML file
The below XML file consists of 3 levels of depth.
src/main/resources/staff.xml
<?xml version="1.0" encoding="utf-8"?>
<company> <!-- Level 1 -->
<staff id="1001"> <!-- Level 2 -->
<name>mkyong</name> <!-- Level 3 -->
<role>support</role> <!-- Level 3 -->
<salary currency="USD">5000</salary>
<!-- for special characters like < &, need CDATA -->
<bio><![CDATA[HTML tag <code>testing</code>]]></bio>
</staff>
<staff id="1002">
<name>yflow</name>
<role>admin</role>
<salary currency="EUR">8000</salary>
<bio><![CDATA[a & b]]></bio>
</staff>
</company>
2. DOM Parser + Recursive Loop
The below example uses a DOM parser and recursive loop to find the depth of the XML level.
CountDepthXmlDom.java
package com.mkyong.xml.dom;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class CountDepthXmlDom {
private static final String FILENAME = "src/main/resources/staff.xml";
private static int DEPTH_XML = 0;
public static void main(String[] args) {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try (InputStream is = new FileInputStream(FILENAME)) {
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(is);
// get all elements
NodeList childNodes = doc.getChildNodes();
printNode(childNodes, 0);
System.out.println("Depth of XML : " + DEPTH_XML);
} catch (ParserConfigurationException | SAXException | IOException e) {
e.printStackTrace();
}
}
// loop recursive
private static void printNode(NodeList nodeList, int level) {
level++;
if (nodeList != null && nodeList.getLength() > 0) {
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
String result = String.format(
"%" + level * 5 + "s : [%s]%n", node.getNodeName(), level);
System.out.print(result);
printNode(node.getChildNodes(), level);
// how depth is it?
if (level > DEPTH_XML) {
DEPTH_XML = level;
}
}
}
}
}
}
Output
Terminal
company : [1]
staff : [2]
name : [3]
role : [3]
salary : [3]
bio : [3]
staff : [2]
name : [3]
role : [3]
salary : [3]
bio : [3]
Depth of XML : 3
3. DOM Parser + Tree Walker
The below example uses DOM’s TreeWalker
to walk the nodes and find the depth of the XML level.
CountDepthXmlDomTreeWalker.java
package com.mkyong.xml.dom;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.traversal.DocumentTraversal;
import org.w3c.dom.traversal.NodeFilter;
import org.w3c.dom.traversal.TreeWalker;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class CountDepthXmlDomTreeWalker {
private static final String FILENAME = "src/main/resources/staff.xml";
private static int DEPTH_XML = 0;
public static void main(String[] args) {
int depth = countDepthXml(FILENAME);
System.out.println("Depth of XML : " + depth);
}
private static int countDepthXml(String filename) {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try (InputStream is = new FileInputStream(filename)) {
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(is);
DocumentTraversal traversal = (DocumentTraversal) doc;
// DOM tree walker
TreeWalker walker = traversal.createTreeWalker(
doc.getDocumentElement(),
NodeFilter.SHOW_ELEMENT,
null,
true);
traverseXmlElements(walker, 0);
} catch (ParserConfigurationException | SAXException | IOException e) {
e.printStackTrace();
}
return DEPTH_XML;
}
private static void traverseXmlElements(TreeWalker walker, int level) {
level++;
Node node = walker.getCurrentNode();
String result = String.format(
"%" + level * 5 + "s : [%s]%n", node.getNodeName(), level);
System.out.print(result);
for (Node n = walker.firstChild();
n != null;
n = walker.nextSibling()) {
traverseXmlElements(walker, level);
}
walker.setCurrentNode(node);
// how depth is it?
if (level > DEPTH_XML) {
DEPTH_XML = level;
}
}
}
Output
Terminal
company : [1]
staff : [2]
name : [3]
role : [3]
salary : [3]
bio : [3]
staff : [2]
name : [3]
role : [3]
salary : [3]
bio : [3]
Depth of XML : 3
4. Download Source Code
$ git clone https://github.com/mkyong/core-java
$ cd java-xml
$ cd src/main/java/com/mkyong/xml/dom/
Such an elegant way to implement recursion !
Very helpful, thanks