This project is a Scala implementation of the W3C Selectors Level 3 specification. I've already created one such implementation in Java, but Scala is my language of choice on the JVM nowadays.
There's some built in support for XPath like expressions in the Scala library, but they are quite rudimentary. I also wanted to dig deeper into the parser combinators and this project seemed like a good way to do that.
The default implementation works with the XML classes provided by the standard Scala library, but the parser and its support classes may be used independent of the actual XML implementation.
Pseudo elements are parsed but not used when selecting nodes. It
doesn't make much sense to look for a::hover etc outside of a web browser.
See example usage below for more info.
*any elementEan element of type EE[foo]an E element with a "foo" attributeE[foo="bar"]an E element whose "foo" attribute value is exactly equal to "bar"E[foo~="bar"]an E element whose "foo" attribute value is a list of whitespace-separated values, one of which is exactly equal to "bar"E[foo^="bar"]an E element whose "foo" attribute value begins exactly with the string "bar"E[foo$="bar"]an E element whose "foo" attribute value ends exactly with the string "bar"E[foo*="bar"]an E element whose "foo" attribute value contains the substring "bar"E[foo|="en"]an E element whose "foo" attribute has a hyphen-separated list of values beginning (from the left) with "en"E:rootan E element, root of the document or the root element specifiedE:nth-child(n)an E element, the n-th child of its parentE:nth-last-child(n)an E element, the n-th child of its parent, counting from the last oneE:nth-of-type(n)an E element, the n-th sibling of its typeE:nth-last-of-type(n)an E element, the n-th sibling of its type, counting from the last oneE:first-childan E element, first child of its parentE:last-childan E element, last child of its parentE:first-of-typean E element, first sibling of its typeE:last-of-typean E element, last sibling of its typeE:only-childan E element, only child of its parentE:only-of-typean E element, only sibling of its typeE:emptyan E element that has no children (including text nodes)E#myidan E element with ID equal to "myid".E:not(s)an E element that does not match simple selector sE Fan F element descendant of an E elementE > Fan F element child of an E elementE + Fan F element immediately preceded by an E elementE ~ Fan F element preceded by an E element
Suppose you have a scala.xml.Elem in a variable named elem that
you'd like to query using CSS selectors:
val result = Selectors.query("div:nth-child(2n)", elem)This will return an Either[String, List[Node]] where Left
indicates a parser error. I.e. if the specified selector string
couldn't be parsed correctly.
It's also possible to query using a pre-parsed selector string. This is the best choice if querying more than once for the same selector string since it only needs to be parsed once.
val selectorGroups = SelectorParser.parse("div:nth-child(2n)") match {
case SelectorParser.Success(selectorGroups) => selectorGroups
case SelectorParser.Failure(msg) => error("Parse error: " + msg)
}
val nodes = Selectors.query(selectorGroups, elem)By importing Selectors._ you can also query like this:
elem $ "div > div"
elem $ selectorGroups
elem.cssQuery("div > div")
elem.cssQuery(selectorGroups)Both $ and cssQuery returns a List[Node]. If the selector string
specified causes a parser error an exception will be thrown. I think
this makes much more sense when the actual element is in focus.
This project uses SBT as its build tool.
Releases are synced to Maven central via Sonatype.
"se.fishtank" %% "css-selectors-scala" % versionThe versions available can be found in the repo or by looking at the tags for this project.