An element within its context.
An element within its context. In other words, an element as a pair containing the root element (of an underlying element type) and a path (from that root element) to this element. More precisely, this element implementation contains an underlying root element, a Path, and an underlying element found from the root element following the Path. It also contains an optional URI of the containing document, if any.
See the documentation of the mixed-in query API trait(s) for more details on the uniform query API offered by this class.
An IndexedClarkElem(underlyingRootElem)
can be seen as one immutable snapshot of an XML tree. All queries (using the ElemApi
uniform
query API) on that snapshot return results within the same snapshot. Take care not to mix up query results from different
snapshots. (This could have been modeled in an alternative design of the class, but such a design has not been chosen.)
Using IndexedClarkElem objects, it is easy to get the ancestry or siblings of an element, as elements of the underlying element type.
Be careful not to create any memory leaks. After all, an element, even a leaf element, typically keeps the entire underlying document element tree as state. Hence the underlying document element tree will always remain in memory if at least one indexed element contains it in its state. (Yet with mutable org.w3c.dom element trees, it is also easy to cause memory leaks. See http://apmblog.compuware.com/2011/04/20/the-top-java-memory-problems-part-1/.)
The optional parent base URI is stored for very fast (optional) base URI computation. This is helpful in an XBRL context, where URI resolution against a base URI is typically a very frequent operation.
The following example code shows how to query for elements with a known ancestry, regardless of the element implementation, if efficiency is not important:
val iBookstore = IndexedClarkElem(bookstore) val iTheBookAuthors = for { iAuthor <- iBookstore.filterElems(withLocalName("Author")) bookPath <- iAuthor.path.findAncestorPath(_.elementNameOption.map(_.localPart) == Some("Book")) iBook <- iBookstore.findElem(_.path == bookPath) if iBook.getChildElem(withLocalName("Title")).elem.text.startsWith("Programming in Scala") } yield iAuthor
In order to use this class, this more formal section can safely be skipped.
The
class can be understood in a precise mathematical sense, as shown below.IndexedClarkElem
Some properties of IndexedClarkElems are as follows:
// All elements (obtained from querying other elements) have the same rootElem iElem.findAllElemsOrSelf.map(_.rootElem).distinct == List(iElem.rootElem) iElem.findAllElemsOrSelf.map(_.underlyingRootElem).distinct == List(iElem.underlyingRootElem) // The correspondence between rootElem, path and elem iElem.findAllElemsOrSelf.forall(e => e.rootElem.findElemOrSelfByPath(e.path).get == e) iElem.findAllElemsOrSelf.forall(e => e.underlyingRootElem.findElemOrSelfByPath(e.path).get == e.underlyingElem)
The correspondence between queries on IndexedClarkElems and the same queries on the underlying elements is as follows:
// Let p be a function from underlying element type E to Boolean iElem.rootElem.filterElemsOrSelf(e => p(e.underlyingElem)).map(_.underlyingElem) == iElem.underlyingRootElem.filterElemsOrSelf(p)
Analogous properties hold for the other query methods.
Node super-type of indexed Clark elements.