Skip to content

Instantly share code, notes, and snippets.

@duanebester
Last active August 29, 2015 14:20
Show Gist options
  • Save duanebester/08d266d894ba2f577fb5 to your computer and use it in GitHub Desktop.
Save duanebester/08d266d894ba2f577fb5 to your computer and use it in GitHub Desktop.
import java.io.ByteArrayInputStream
import javax.xml.parsers.DocumentBuilderFactory
import org.w3c.dom._
val factory = DocumentBuilderFactory.newInstance()
val builder = factory.newDocumentBuilder();
val content = """<start>
<div id="header_nav">
<div class="avatar">
<img width="40" />
</div>
<a class="logged-in">Name</a>
<ul>
<li>
<a>link</a>
</li>
<li>
<a>link2</a>
</li>
</ul>
<form id="search" />
</div>
</start>"""
// Convert to bytes
val input = new ByteArrayInputStream(content getBytes())
// Parse into Document
val document = builder.parse(input)
// Helper function to find the Node with the id (header_nav) we want.
def findDivWithId(d:Document, id:String):Option[Node] = {
val list: NodeList = d.getElementsByTagName("div")
for(x <- 0 to list.getLength)
{
if(list.item(x).hasAttributes){
val attrs:NamedNodeMap = list.item(x).getAttributes
for(y <- 0 to attrs.getLength)
{
val attr = attrs.item(y).asInstanceOf[Attr];
if(attr.getName.toLowerCase == "id" && attr.getValue.toLowerCase == id)
{
return Some(list.item(x));
}
}
}
}
return None;
}
// Recursive Function for counting descendants
def countSubNodes(n:Node):Int = {
var current = 1
// The W3C API will give text nodes in their implementation.
// I'm assuming our theoretical Node class won't return these,
// So I just don't count them.
if(n.getNodeName.charAt(0) == '#')
{
current = 0;
}
if(n.getFirstChild != null){
current += countSubNodes(n.getFirstChild)
}
if(n.getNextSibling != null){
current += countSubNodes(n.getNextSibling)
}
current
}
def countDescendants(n:Node):Int = {
if(n == null)
{
return 0
}
// Must have at least one child to begin DOM traversing
if(n.getFirstChild == null) {
0
}
else {
countSubNodes(n.getFirstChild);
}
}
// Find our node
// TODO: Add a null check, I have wrapped this in a Scala Option though,
// so the correct way to call would be .getOrElse(...)
val node = findDivWithId(document, "header_nav").get
// Count 'em up
countDescendants(node)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment