Last active
August 29, 2015 14:20
-
-
Save duanebester/08d266d894ba2f577fb5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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