Created
September 21, 2011 16:48
-
-
Save jprudent/1232619 to your computer and use it in GitHub Desktop.
Adding a given class on first level paragraph and heading elements of XHTML document (for memo)
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
object XhtmlTransformer { | |
import xml.transform.RuleTransformer | |
/ | |
val className = MonocleReader.className | |
object XhtmlRewriter extends RewriteRule { | |
/** | |
* A regex to match our className | |
*/ | |
val markerRE = """\b%s\b""".format(className).r | |
/** | |
* @param node may be any element (p,div,span) | |
* @return true if root is a paragraph or a heading | |
*/ | |
def isReadingMaterial(node: Node): Boolean = node.label.matches("p|h\\d") | |
/** | |
* @param node may be any element (p,div,span) | |
* @return true if node has a class attribute which value contains className | |
*/ | |
def hasMark(node: Node): Boolean = { | |
import xml.Text | |
//an attribute has several nodes | |
//we try to Find a Text node which contains our className | |
node.attribute("class").map(_.exists(_ match { | |
case Text(value) => markerRE.findFirstIn(value).isDefined | |
case _ => false | |
})).getOrElse(false) | |
} | |
/** | |
* @param node should receive a reading material element | |
* @return the modified node withe an attribute class that contains | |
* className. The subtree is not modified | |
*/ | |
def addMarker(n: Node): Seq[Node] = { | |
import xml.{Null, UnprefixedAttribute, Elem, Text} | |
val newClassAttributeValue = if (n.attribute("class").isDefined) { | |
//an attribute value is a Seq[Node] | |
n.attribute("class").get.map(_ match { | |
case Text(value) => new Text(value + " " + className) | |
case n => n | |
}) | |
} else { | |
new Text(MonocleReader.className) | |
} | |
val newClassAttribute = new UnprefixedAttribute("class", newClassAttributeValue, Null) | |
val newAttributes = n.attributes.remove("class").append(newClassAttribute) | |
Elem(n.prefix, n.label, newAttributes, n.scope, n.child: _*) | |
} | |
override def transform(n: Node): Seq[Node] = { | |
if (isReadingMaterial(n) && !hasMark(n)) addMarker(n) | |
else n | |
} | |
} | |
object XhtmlRuleTransformer extends RuleTransformer(XhtmlRewriter) | |
/** | |
* @param node is the XML to modify | |
* @return An XML where a given class on first level paragraph and heading | |
* elements of XHTML document is added to attribute "class" or created if | |
* it doesn't exists | |
*/ | |
def transform(node: Node): Node = XhtmlRuleTransformer(node) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Here is some tests:
it should "transform an xml" in {
import service.reader.XhtmlTransformer
import play.Logger
import xml.{Node, PrettyPrinter}
}