import scala.xml._ ;
import scala.xml.dtd._ ;
import org.xml.sax.InputSource ;
/* a former version of Scala used regular expression patterns, like
* in the following code. In the future, we plan to reactivate some
* well-behaved regular expressions again
// gimmick: text replacement "scalac" => <code>scalac</code>
def cook(s: String): Seq[Node] = cook1(s) ;
def cook1(s: Seq[Char]):List[Node] = s match {
case Seq( a @ _*, 's','c','a','l','a','c', b @ _* ) =>
Text(cook2( a )) :: <code>scalac</code> :: cook1( b )
case _ => List( Text( cook2( s )))
}
def cook2(s: Seq[Char]): String = {
val r = new StringBuffer();
s.foreach { c:char => val _ = r.append(c); };
r.toString()
}
*/
def transform1(ns: Iterable[Node]): Seq[Node] = {
val zs = new NodeBuffer();
for(val z <- ns) { zs &+ transform( z ) }
zs
}
/** this functions holds "templates" that transform nodes of an input tree
* into an iterable representation of a sequence of nodes of the output
* tree.
*
* It is ok to return a single node, since each node is at the same
* time a singleton sequence. Likewise, the pattern variable x will be
* of type Seq[Node], although here it is always binding a single node.
*/
def transform(n: Node):Iterable[Node] = n match {
case x @ <article>{ ns @ _ * }</article> =>
<source active="ant" title={ (x \ "title" \ "_").toString() }>
<header>
<author>Burak Emir</author>
<keywords>Scala4Ant</keywords>
<style type="text/css"></style>
</header>
<content>
<title><scala/> Ant Task</title>
{ transform1( x \ "_" ) }
</content>
</source>
case x @ <sect1>{ _* }</sect1> =>
<section>{ transform1( x \ "_" ) }</section>
case x @ <title>{ _* }</title> =>
<h>{ x \ "_" }</h>
case x @ <para>{ _* }</para> =>
<p>{ transform1( x \ "_" ) }</p>
case x @ <itemizedlist>{ _* }</itemizedlist> =>
<ul>{ transform1( x \ "_" ) }</ul>
case x @ <listitem>{ _* }</listitem> =>
<li>{ transform1( x \ "_" ) }</li>
case x @ <constant>{ _* }</constant> =>
// an xml:group is a sequence that appears to the scala type system
// as a single node. Here it is used to append a text node with a space
<xml:group><code>{ x \ "_" }</code> </xml:group>
case x @ <programlisting>{ _* }</programlisting> =>
<pre>{ x \ "_" }</pre>
case Elem(namespace, label, attrs, scp, ns @ _*) =>
Elem(namespace, label, attrs, scp, transform1( ns ):_* )
case z =>
z
};
def main(args:Array[String]) = {
if( args.length == 1 ) { // must have one arg
object ConsoleWriter extends java.io.Writer {
def close() = {}
def flush() = Console.flush
def write(cbuf:Array[char], off:int , len:int ): unit = {
var i = 0
while(i < len)
Console.print(cbuf(off + i))
}
}
val src = XML.load(new InputSource( args( 0 ))); //use Java parser
// transform returns an iterable, but we now it is a singleton
// sequence, so we get its first element
val n = transform( src ).elements.next
val doctpe = DocType("html",PublicID("-//W3C//DTD XHTML 1.1//EN","../default.dtd"), Nil)
/** write document to console, with encoding latin1, xml declaration
* and doctype
*/
XML.write(ConsoleWriter, n, "iso-8859-1", true, doctpe)
}
else error("need one arg");
}
}