literals - scalawag/sdom GitHub Wiki
One way to create a ElementSpec is to use Scala's XML literals. Depending on what information you want to retain from the literals, you can specify a conversion strategy. The local name and namespace of each element and attribute is always retained. This means that the documents should be semantically equivalent.
- KeepPrefixes - This strategy keeps the prefixes the same as they were in the literals.
- KeepNamespaces - This strategy keeps the namespace declarations on the same elements they were on in the literal.
- KeepPrefixesAndNamespaces - This strategy is the combination of the above two strategies.
- Flexible - Only the structure of the XML is maintained. This means that SDOM may place may move the namespace declarations and change the prefixes when the document is built.
"Flexible" is the default strategy because it tends to produce the smallest and least cluttered documents.
import org.scalawag.sdom._
import org.scalatest.Matchers._
val s1:ElementSpec = <a xmlns:ns1="NS1"><ns1:b/></a>
s1 shouldEqual ElementSpec(ElementName("a",""),children=Iterable(ElementSpec(ElementName("b","NS1"))))
The elements both have their correct namespaces, but the prefixes and declarations are not specified.
{
import ScalaXmlConversions.Strategies.KeepPrefixes
val s2:ElementSpec = <a xmlns:ns1="NS1"><ns1:b/></a>
s2 shouldEqual ElementSpec(ElementName("a",""),children=Iterable(ElementSpec(ElementName("b","NS1"),prefix=Some("ns1"))))
}
The element "b" now has its prefix set to "ns1". This constraint will be used by SDOM when building the complete document.
{
import ScalaXmlConversions.Strategies.KeepNamespaces
val s3:ElementSpec = <a xmlns:ns1="NS1"><ns1:b/></a>
s3 shouldEqual ElementSpec(ElementName("a",""),children=Iterable(ElementSpec(ElementName("b","NS1"))),namespaces=Iterable(NamespaceSpec("ns1","NS1")))
}
The element "b" now again has no prefix. The element "a" explicitly has a namespace declaration. This constraint will be used by SDOM when building the complete document so that the namespace declaration is guaranteed to be there.
This can be useful because, if you don't care about the specific prefixes used, SDOM can use whatever prefix is available when building the complete document. When a document is built of different elements that come from different modules, this is more likely to happen.
val s4:ElementSpec = <a xmlns="NS1">1</a>
val s5:ElementSpec = <a:a xmlns:a="NS1">1</a:a>
val s6:ElementSpec = ElementSpec(ElementName("b","NS1"),children=Iterable(s4,s5))
Document(s6)
// -> Document(<b xmlns="NS1"><a>1</a><a>1</a></b>)
The resulting document doesn't have all the extra declarations and redundant prefixes. If you specify a stricter interpretation of the literals, the document is a mess. Well, it has everything that the literals had in them including the same namespace declarations and prefixes.
{
import ScalaXmlConversions.Strategies.KeepPrefixesAndNamespaces
val s7:ElementSpec = <a xmlns="NS1">1</a>
val s8:ElementSpec = <a:a xmlns:a="NS1">1</a:a>
val s9:ElementSpec = ElementSpec(ElementName("b","NS1"),children=Iterable(s7,s8))
Document(s9)
// -> Document(<b xmlns="NS1"><a xmlns="NS1">1</a><a xmlns:a="NS1">1</a></b>)
}
You might wonder why you would ever want to produce a document that looks like this. I don't know that you would but maybe you're producing a document that's a template where someone will manually fill in an element and you want to provide the namespace declaration for them even though nothing in the template document uses it. This is the only way to force SDOM to include the declaration.