This is the element transformation part of the yaidom query and update API. Only a few DOM-like element implementations in yaidom mix in this trait (indirectly, because some implementing sub-trait is mixed in), thus sharing this API.
This is the element transformation part of the yaidom query and update API. Only a few DOM-like element implementations in yaidom mix in this trait (indirectly, because some implementing sub-trait is mixed in), thus sharing this API.
'''This trait typically does not show up in application code using yaidom, yet its (uniform) API does. Hence, it makes sense to read the documentation of this trait, knowing that the API is offered by multiple element implementations.'''
This trait is purely abstract. The most common implementation of this trait is eu.cdevreeze.yaidom.queryapi.TransformableElemLike.
That trait only knows how to transform child elements. Using this minimal knowledge, the trait offers methods to transform
descendant elements and descendant-or-self elements. Indeed, the trait is similar to ElemLike
, except that it
transforms elements instead of querying for elements.
The big conceptual difference with "updatable" elements (in trait UpdatableElemLike[N, E]
) is that "transformations" are
about applying some transforming function to an element tree, while "(functional) updates" are about "updates" at given paths.
==TransformableElemApi examples==
To illustrate the use of this API, consider the following example XML:
<book:Bookstore xmlns:book="http://bookstore/book" xmlns:auth="http://bookstore/author">
<book:Book ISBN="978-0321356680" Price="35" Edition="2">
<book:Title>Effective Java (2nd Edition)</book:Title>
<book:Authors>
<auth:Author>
<auth:First_Name>Joshua</auth:First_Name>
<auth:Last_Name>Bloch</auth:Last_Name>
</auth:Author>
</book:Authors>
</book:Book>
<book:Book ISBN="978-0981531649" Price="35" Edition="2">
<book:Title>Programming in Scala: A Comprehensive Step-by-Step Guide, 2nd Edition</book:Title>
<book:Authors>
<auth:Author>
<auth:First_Name>Martin</auth:First_Name>
<auth:Last_Name>Odersky</auth:Last_Name>
</auth:Author>
<auth:Author>
<auth:First_Name>Lex</auth:First_Name>
<auth:Last_Name>Spoon</auth:Last_Name>
</auth:Author>
<auth:Author>
<auth:First_Name>Bill</auth:First_Name>
<auth:Last_Name>Venners</auth:Last_Name>
</auth:Author>
</book:Authors>
</book:Book>
</book:Bookstore>
Suppose this XML has been parsed into eu.cdevreeze.yaidom.simple.Elem variable named bookstoreElem
. Then we can combine
author first and last names as follows:
val authorNamespace = "http://bookstore/author"
bookstoreElem = bookstoreElem transformElems {
case elem: Elem if elem.resolvedName == EName(authorNamespace, "Author") =>
val firstName = (elem \ (_.localName == "First_Name")).headOption.map(_.text).getOrElse("")
val lastName = (elem \ (_.localName == "Last_Name")).headOption.map(_.text).getOrElse("")
val name = (firstName + " " + lastName).trim
Node.textElem(QName("auth:Author"), elem.scope ++ Scope.from("auth" -> authorNamespace), name)
case elem: Elem => elem
}
bookstoreElem = bookstoreElem.prettify(2)
When using the TransformableElemApi
API, keep the following in mind:
-
The
transformElems
andtransformElemsOrSelf
methods (and their Node sequence producing counterparts) may produce a lot of "garbage". If only a small portion of an element tree needs to be updated, the "update" methods in traitUpdatableElemApi
may be a better fit. -
Transformations operate in a bottom-up manner. This implies that parent scopes cannot be used for transforming child elements. Hence, namespace undeclarations may result, which are not allowed in XML 1.0 (except for the default namespace).
Top-down transformations are still possible, by combining recursion with method transformChildElems
(or
transformChildElemsToNodeSeq
). For example:
def removePrefixedNamespaceUndeclarations(elem: Elem): Elem = {
elem transformChildElems { e =>
val newE = e.copy(scope = elem.scope.withoutDefaultNamespace ++ e.scope)
removePrefixedNamespaceUndeclarations(newE)
}
}
- Authors
Chris de Vreeze
- Companion
- object
Type members
Types
Inherited types
The node type, that is a super-type of the element type, but also of corresponding text node types etc.
The node type, that is a super-type of the element type, but also of corresponding text node types etc.
- Inherited from
- AnyElemNodeApi
Value members
Abstract methods
Returns the same element, except that child elements have been replaced by applying the given function. Non-element child nodes occur in the result element unaltered.
Returns the same element, except that child elements have been replaced by applying the given function. Non-element child nodes occur in the result element unaltered.
That is, returns the equivalent of:
val newChildren =
children map {
case e: E => f(e)
case n: N => n
}
withChildren(newChildren)
Returns the same element, except that child elements have been replaced by applying the given function. Non-element child nodes occur in the result element unaltered.
Returns the same element, except that child elements have been replaced by applying the given function. Non-element child nodes occur in the result element unaltered.
That is, returns the equivalent of:
val newChildren =
children flatMap {
case e: E => f(e)
case n: N => Vector(n)
}
withChildren(newChildren)
Transforms the element by applying the given function to all its descendant elements, in a bottom-up manner.
Transforms the element by applying the given function to all its descendant elements, in a bottom-up manner.
That is, returns the equivalent of:
transformChildElems (e => e.transformElemsOrSelf(f))
Transforms the element by applying the given function to all its descendant-or-self elements, in a bottom-up manner.
Transforms the element by applying the given function to all its descendant-or-self elements, in a bottom-up manner.
That is, returns the equivalent of:
f(transformChildElems (e => e.transformElemsOrSelf(f)))
In other words, returns the equivalent of:
f(transformElems(f))
Transforms each descendant element to a node sequence by applying the given function to all its descendant-or-self elements, in a bottom-up manner.
Transforms each descendant element to a node sequence by applying the given function to all its descendant-or-self elements, in a bottom-up manner.
That is, returns the equivalent of:
f(transformChildElemsToNodeSeq(e => e.transformElemsOrSelfToNodeSeq(f)))
In other words, returns the equivalent of:
f(transformElemsToNodeSeq(f))
Transforms each descendant element to a node sequence by applying the given function to all its descendant elements, in a bottom-up manner. The function is not applied to this element itself.
Transforms each descendant element to a node sequence by applying the given function to all its descendant elements, in a bottom-up manner. The function is not applied to this element itself.
That is, returns the equivalent of:
transformChildElemsToNodeSeq(e => e.transformElemsOrSelfToNodeSeq(f))
It is equivalent to the following expression:
transformElemsOrSelf { e => e.transformChildElemsToNodeSeq(che => f(che)) }