From d36d1e0e4c95a8082e5b6e8141d854ad98e79218 Mon Sep 17 00:00:00 2001 From: buraq Date: Wed, 27 Aug 2003 10:23:08 +0000 Subject: added attributes to generic xml representation --- sources/scala/xml/Element.scala | 5 +- sources/scala/xml/Generic.scala | 106 ++++++++++++++++++++++++---- sources/scala/xml/PCDATA.scala | 18 ++++- sources/scala/xml/ScalaFactoryAdapter.scala | 50 ++++--------- 4 files changed, 127 insertions(+), 52 deletions(-) (limited to 'sources') diff --git a/sources/scala/xml/Element.scala b/sources/scala/xml/Element.scala index e4d24f1918..0dce66ab1b 100644 --- a/sources/scala/xml/Element.scala +++ b/sources/scala/xml/Element.scala @@ -18,7 +18,7 @@ abstract class Element { override def hashCode() = Element.hashValue( getName, getAttribs, getChildren ); def toXML: String = { - "<" + getName + toXML_( getAttribs ) + ">" + "<" + getName + Generic.toXML( getAttribs ) + ">" + toXML_( getChildren ) + "" } @@ -28,6 +28,7 @@ abstract class Element { case Nil => ""; } + /* def toXML_( attrib:Map[ String, String ] ):String = { def iterate( keys:Iterator[String] ) = if( keys.hasNext ) @@ -42,7 +43,7 @@ abstract class Element { if( attrib != null ) iterate( attrib.keys.elements ) else ""; } - +*/ override def toString() = getName.concat("(").concat(getChildren.toString().concat(")")); /* diff --git a/sources/scala/xml/Generic.scala b/sources/scala/xml/Generic.scala index ac649d4656..bc760bcfef 100644 --- a/sources/scala/xml/Generic.scala +++ b/sources/scala/xml/Generic.scala @@ -1,5 +1,9 @@ package scala.xml; +import scala.xml.javaAdapter.Map ; +import scala.xml.javaAdapter.HashMap ; + + /** Generic.load( ) will load the xml document from file and * create a tree with scala.Labelled, PCDATA and scala.Symbol objects. * Text can appear within PCDATA at the leaves. @@ -7,33 +11,109 @@ package scala.xml; object Generic { + // utility functions + + def iterToList[ a ]( iter:java.util.Iterator ):List[a] = + if( !iter.hasNext() ) + Nil + else + (iter.next().asInstanceOf[ a ])::iterToList( iter ) ; + + def mapToMap[a,b]( map:java.util.Map ):Map[a,b] = { + + val keys:java.util.Iterator = map.keySet().iterator(); + val res = new HashMap[a,b] ; + + def iterToMap:Unit = + if( keys.hasNext() ) { + val key = keys.next(); + val value = map.get( key ).asInstanceOf[ b ]; + res.put( key.asInstanceOf[ a ], value.asInstanceOf[ b ]); + iterToMap + } else + () ; + + iterToMap; + res + } + + def toXML( attrib:Map[ String, String ] ):String = { + def iterate( keys:Iterator[String] ) = + if( keys.hasNext ) { + val key = keys.next; + " " + key + "=\"" + attrib.get( key ) + "\""; + } else { + "" + } + + if( attrib != null ) iterate( attrib.keys.elements ) else ""; + } + + // attributes + + trait Attribbed { + + // only CDATA / String attributes for now + def attribs : Map[String,String] ; + + } + // functions for generic xml loading, saving + def load( filename:String ):Labelled = { val b = new GenericFactoryAdapter().loadXML( filename ); b.asInstanceOf[Labelled] }; - class GenericFactoryAdapter extends FactoryAdapter() { + def save( filename:String, doc:Any ):Unit = { + import java.io.{FileOutputStream,Writer}; + import java.nio.channels.{Channels,FileChannel}; + def toXML( xs: List[Any], fc:Writer ):Unit = xs match { + case _::ys => + toXML( xs.head, fc ); + toXML( ys, fc ); + case _ => () + } + def toXML( doc: Any, fc:Writer ):Unit = doc match { + case PCDATA( s ) => + fc.write( (doc.asInstanceOf[ PCDATA ]).toXML ); + case Labelled( Symbol( tag ), xs ) => + fc.write( "<" ); + fc.write( tag ); + fc.write( Generic.toXML(( doc.asInstanceOf[ Attribbed ]) + .attribs )); + fc.write( ">" ); + toXML( xs, fc ); + fc.write( "" ); - import scala.xml.javaAdapter.Map ; - import scala.xml.javaAdapter.HashMap ; + } + val fos = new FileOutputStream( filename ); + val w = Channels.newWriter( fos.getChannel(), "ISO-8859-1" ); + toXML( doc, w ); + w.close(); + fos.close(); + } - def iterToList[ a ]( iter:java.util.Iterator ):List[a] = - if( !iter.hasNext() ) - Nil - else - (iter.next().asInstanceOf[a])::iterToList( iter ) ; + class GenericFactoryAdapter extends FactoryAdapter() { def elementContainsText( name:java.lang.String ):boolean = true; // default behaviour is hash-consing val cache = new HashMap(); - def createElement( elemName:String, - attribs :java.util.Map, // ignore attributes. - children:java.util.Iterator ):scala.Object = { + def createElement( elemName: String, + attrs: java.util.Map, + children: java.util.Iterator ):scala.Object = { + + val el = new Labelled( Symbol( elemName ), + Generic.iterToList[ Any ]( children )) + with Attribbed { + def attribs = Generic.mapToMap[String,String]( attrs ); + }; - val el = Labelled( Symbol( elemName), iterToList[ Any ]( children )); - val el_cache = cache.get( el.asInstanceOf[scala.All]).asInstanceOf[scala.Object]; + val el_cache = cache.get( el.asInstanceOf[scala.All]) + .asInstanceOf[scala.Object]; if ( el_cache != null ) { System.err.println("[using cached elem!]"); el_cache diff --git a/sources/scala/xml/PCDATA.scala b/sources/scala/xml/PCDATA.scala index 70d849f3bf..5b9aa01c1a 100644 --- a/sources/scala/xml/PCDATA.scala +++ b/sources/scala/xml/PCDATA.scala @@ -12,7 +12,23 @@ case class PCDATA( content:String ) extends Element { def getAttribs = error("PCDATA.getAttribs"); def setAttribs( m:Map[ String, String ] ):Unit = error("PCDATA.setAttribs"); - override def toXML:String = content; + override def toXML:String = { + // new java.util.StringBuffer !!crashes!! + val s = new StringBuffer(); + var i = 0; + while( i < content.length() ) { + val c = content.charAt( i ); + c match { + case '<' => s.append("<"); + case '>' => s.append(">"); + case '&' => s.append("&"); + case '"' => s.append("""); + case _ => s.append( c ); + } + i = i + 1; + } + s.toString(); + } override def hashCode() = content.hashCode(); override def toString() = "PCDATA("+content+")"; diff --git a/sources/scala/xml/ScalaFactoryAdapter.scala b/sources/scala/xml/ScalaFactoryAdapter.scala index 2a777c6e38..600357b6cd 100644 --- a/sources/scala/xml/ScalaFactoryAdapter.scala +++ b/sources/scala/xml/ScalaFactoryAdapter.scala @@ -3,45 +3,23 @@ package scala.xml ; import scala.xml.javaAdapter.Map ; import scala.xml.javaAdapter.HashMap ; -/** a Scala specific dtd2scala.FactoryAdapter, which plays the SAX content handler for the SAX parser - * It implements the three callback methods elementContainsText, createElement and createPCDATA. - * DTDs imported with the dtd2scala tool all use this class as interface to the SAX XML parser, by - * giving concrete values for the factory maps f and g. - */ +/** a Scala specific dtd2scala.FactoryAdapter, which plays the SAX content +* handler for the SAX parser. It implements the three callback methods +* elementContainsText, createElement and createPCDATA. DTDs imported with +* the dtd2scala tool all use this class as interface to the SAX XML parser, +* by giving concrete values for the factory maps f and g. +*/ abstract class ScalaFactoryAdapter extends FactoryAdapter() { - def iterToList[ a ]( iter:java.util.Iterator ):List[a] = - if( !iter.hasNext() ) - Nil - else - (iter.next().asInstanceOf[a])::iterToList( iter ) ; - - - def mapToMap[a,b]( map:java.util.Map ):Map[a,b] = { - - val keys:java.util.Iterator = map.keySet().iterator(); - val res = new HashMap[a,b] ; - - def iterToMap:Unit = - if( keys.hasNext() ) { - val key = keys.next(); - val value = map.get( key ).asInstanceOf[b] ; - res.put( key.asInstanceOf[a] , value.asInstanceOf[b] ); - iterToMap - } else - () ; - - iterToMap; - res - } - - /** a mapping from a element name (string) to an element constructor (constr:Seq[Element] => Element) - */ + /** a mapping from a element name (string) to an element constructor + * (constr:Seq[Element] => Element) + */ val f: Map[ String, Seq[Element] => Element ]; - /** a mapping from an element name (string) to a truth value indicating whether text (PCDATA) may appear as + /** a mapping from an element name (string) to a truth value indicating + * whether text (PCDATA) may appear as */ val g: Map[ String, boolean ] ; @@ -57,11 +35,11 @@ abstract class ScalaFactoryAdapter def createElement(elemName:String, attribs:java.util.Map, children:java.util.Iterator ):scala.Object = { - val _children = iterToList[Element]( children ); // 2do:optimize + val _children = Generic.iterToList[Element]( children ); // 2do:optimize if( !compress ) { val c = f.get( elemName ); // get constructor val el = c( _children ); - el.setAttribs( mapToMap[String,String]( attribs ) ); + el.setAttribs( Generic.mapToMap[String,String]( attribs ) ); el } else { // do hash-consing @@ -72,7 +50,7 @@ abstract class ScalaFactoryAdapter } else { val c = f.get( elemName ); // get constructor val el = c( _children ); - el.setAttribs( mapToMap[String,String]( attribs ) ); + el.setAttribs( Generic.mapToMap[String,String]( attribs ) ); cache.put( h.asInstanceOf[scala.All], el.asInstanceOf[scala.All] ); el } -- cgit v1.2.3