Răsfoiți Sursa

2003-08-18 Ben Maurer <[email protected]>

	* System.Xml.dll.sources: add files from Oleg.
	* *.cs: Support for xsl:output. (Oleg)

svn path=/trunk/mcs/; revision=17388
Ben Maurer 22 ani în urmă
părinte
comite
ec458973a1

+ 4 - 0
mcs/class/System.XML/ChangeLog

@@ -1,3 +1,7 @@
+2003-08-18 Ben Maurer  <[email protected]>
+
+	* System.Xml.dll.sources: add files from Oleg.
+
 2003-08-18 Ben Maurer  <[email protected]>
 
 	* System.Xml.dll.source: add System.Xml/HighWaterStack.cs.

+ 4 - 0
mcs/class/System.XML/Mono.Xml.Xsl.Operations/ChangeLog

@@ -1,3 +1,7 @@
+2003-08-18 Ben Maurer  <[email protected]>
+
+	* *.cs: Support for xsl:output. (Oleg)
+
 2003-08-17 Ben Maurer  <[email protected]>
 
 	* XslCopyOf.cs: handle default ns

+ 4 - 3
mcs/class/System.XML/Mono.Xml.Xsl.Operations/XslComment.cs

@@ -34,9 +34,10 @@ namespace Mono.Xml.Xsl.Operations {
 		public override void Evaluate (XslTransformProcessor p)
 		{
 			StringWriter s = new StringWriter ();
-			XmlWriter w = new XmlTextWriter (s);
-			
-			p.PushOutput (w);
+			//TODO: only text nodes allowed here, other nodes must be ignored along with any content,
+			//so TextOutputter is not really suitable here
+			Outputter outputter = new TextOutputter(s);			
+			p.PushOutput (outputter);
 			value.Evaluate (p);
 			p.PopOutput ();
 			

+ 13 - 13
mcs/class/System.XML/Mono.Xml.Xsl.Operations/XslCopyOf.cs

@@ -25,25 +25,25 @@ namespace Mono.Xml.Xsl.Operations {
 			select = c.CompileExpression (c.GetAttribute ("select"));
 		}
 			
-		void CopyNode (XmlWriter w, XPathNavigator nav)
+		void CopyNode (Outputter outputter, XPathNavigator nav)
 		{
 			switch (nav.NodeType) {
 			case XPathNodeType.Root:
 				XPathNodeIterator itr = nav.SelectChildren (XPathNodeType.All);
 				while (itr.MoveNext ())
-					CopyNode (w, itr.Current);
+					CopyNode (outputter, itr.Current);
 				break;
 				
 			case XPathNodeType.Element:
-				w.WriteStartElement (nav.Prefix, nav.LocalName, nav.NamespaceURI);
+				outputter.WriteStartElement (nav.Prefix, nav.LocalName, nav.NamespaceURI);
 				
 				if (nav.MoveToFirstNamespace (XPathNamespaceScope.Local))
 				{
 					do {
 						if (nav.Name != "")
-							w.WriteAttributeString ("xmlns", nav.Name, null, nav.Value);
+							outputter.WriteAttributeString ("xmlns", nav.Name, null, nav.Value);
 						else 
-							w.WriteAttributeString ("xmlns", nav.Value);
+							outputter.WriteAttributeString ("xmlns", nav.Value);
 					} while (nav.MoveToNextNamespace (XPathNamespaceScope.Local));
 					nav.MoveToParent ();
 				}
@@ -51,33 +51,33 @@ namespace Mono.Xml.Xsl.Operations {
 				if (nav.MoveToFirstAttribute())
 				{
 					do {
-						w.WriteStartAttribute (nav.Prefix, nav.LocalName, nav.NamespaceURI);
-						w.WriteString (nav.Value);
-						w.WriteEndAttribute (); 
+						outputter.WriteStartAttribute (nav.Prefix, nav.LocalName, nav.NamespaceURI);
+						outputter.WriteString (nav.Value);
+						outputter.WriteEndAttribute (); 
 					} while (nav.MoveToNextAttribute ());
 					nav.MoveToParent();
 				}
 				
 				if (nav.MoveToFirstChild ()) {
 					do {
-						CopyNode (w, nav);
+						CopyNode (outputter, nav);
 					} while (nav.MoveToNext ());
 					nav.MoveToParent ();
 				}
 				
-				w.WriteEndElement ();
+				outputter.WriteEndElement ();
 				break;
 			case XPathNodeType.Whitespace:                                                     
 
 			case XPathNodeType.SignificantWhitespace:
 			case XPathNodeType.Text:
-				w.WriteString (nav.Value);
+				outputter.WriteString (nav.Value);
 				break;
 			case XPathNodeType.ProcessingInstruction:
-				w.WriteProcessingInstruction (nav.Name, nav.Value);
+				outputter.WriteProcessingInstruction (nav.Name, nav.Value);
 				break;
 			case XPathNodeType.Comment:
-				w.WriteComment (nav.Value);
+				outputter.WriteComment (nav.Value);
 				break;
 			}			
 		}

+ 2 - 1
mcs/class/System.XML/Mono.Xml.Xsl.Operations/XslMessage.cs

@@ -34,7 +34,8 @@ namespace Mono.Xml.Xsl.Operations {
 		public override void Evaluate (XslTransformProcessor p)
 		{
 			if (children != null) {
-				p.PushOutput (new XmlTextWriter (Console.Error));
+				//TODO: Which outputter to use here?
+				p.PushOutput (new TextOutputter(Console.Error));
 				children.Evaluate (p);
 				p.PopOutput ();
 			}

+ 4 - 3
mcs/class/System.XML/Mono.Xml.Xsl.Operations/XslProcessingInstruction.cs

@@ -35,9 +35,10 @@ namespace Mono.Xml.Xsl.Operations {
 		public override void Evaluate (XslTransformProcessor p)
 		{
 			StringWriter s = new StringWriter ();
-			XmlWriter w = new XmlTextWriter (s);
-			
-			p.PushOutput (w);
+			//TODO: only text nodes allowed here, other nodes must be ignored along with any content,
+			//so TextOutputter is not really suitable here
+			Outputter outputter = new TextOutputter(s);
+			p.PushOutput (outputter);
 			value.Evaluate (p);
 			p.PopOutput ();
 			

+ 3 - 1
mcs/class/System.XML/Mono.Xml.Xsl.Operations/XslVariable.cs

@@ -46,7 +46,9 @@ namespace Mono.Xml.Xsl.Operations {
 				return p.Evaluate (select);
 			} else if (content != null) {
 				XmlNodeWriter w = new XmlNodeWriter ();
-				p.PushOutput (w);
+				//TODO: which outputter should be used here?
+				Outputter outputter = new XmlOutputter(w, p.CompiledStyle.Style.Outputs);
+				p.PushOutput (outputter);
 				content.Evaluate (p);
 				p.PopOutput ();
 				return w.Document.CreateNavigator ().SelectChildren (XPathNodeType.All);

+ 4 - 0
mcs/class/System.XML/Mono.Xml.Xsl/ChangeLog

@@ -1,3 +1,7 @@
+2003-08-18 Ben Maurer  <[email protected]>
+
+	* *.cs: Support for xsl:output.
+
 2003-08-17 Ben Maurer  <[email protected]>
 
 	* Compiler.cs: handle extension and excluded namespaces.

+ 34 - 0
mcs/class/System.XML/Mono.Xml.Xsl/Outputter.cs

@@ -0,0 +1,34 @@
+//
+// Outputter.cs
+//
+// Authors:
+//	Oleg Tkachenko ([email protected])
+//	
+// (C) 2003 Oleg Tkachenko
+//
+
+using System;
+
+namespace Mono.Xml.Xsl {
+	/// <summary>
+	/// Abstract XSLT outputter. 
+	/// Implementations of this class outputs result tree according output method.
+	/// </summary>
+	public abstract class Outputter {		
+		public abstract void WriteStartDocument();			
+		public abstract void WriteEndDocument();
+		public abstract void WriteStartElement(string localName, string nsURI);
+		public abstract void WriteStartElement(string prefix, string localName, string nsURI);
+		public abstract void WriteEndElement();
+		public abstract void WriteAttributeString(string localName, string value);
+		public abstract void WriteAttributeString(string prefix, string localName, string nsURI, string value);
+		public abstract void WriteStartAttribute(string localName, string nsURI);
+		public abstract void WriteStartAttribute(string prefix, string localName, string nsURI);
+		public abstract void WriteEndAttribute();		
+		public abstract void WriteComment(string text);
+		public abstract void WriteProcessingInstruction(string name, string text);
+		public abstract void WriteString(string text);
+		public abstract void WriteRaw(string data);
+		public abstract void Close();
+	}
+}

+ 61 - 0
mcs/class/System.XML/Mono.Xml.Xsl/TextOutputter.cs

@@ -0,0 +1,61 @@
+//
+// TextOutputter.cs
+//
+// Authors:
+//	Oleg Tkachenko ([email protected])
+//	
+// (C) 2003 Oleg Tkachenko
+//
+
+using System;
+using System.Xml;
+using System.IO;
+
+namespace Mono.Xml.Xsl {
+	/// <summary>
+	/// Outputter implementation for text output method
+	/// </summary>
+	public class TextOutputter : Outputter {
+		private TextWriter _writer;
+		
+		public TextOutputter(TextWriter w) {
+			_writer = w;
+		}
+
+		public override void WriteStartDocument() {}
+		
+		public override void WriteEndDocument() {}
+
+		public override void WriteStartElement(string localName, string nsURI) {}
+
+		public override void WriteStartElement(string prefix, string localName, string nsURI) {}
+
+		public override void WriteEndElement() {}
+
+		public override void WriteAttributeString(string localName, string value) {}
+
+		public override void WriteAttributeString(string prefix, string localName, string nsURI, string value) {}
+
+		public override void WriteStartAttribute(string localName, string nsURI) {}
+
+		public override void WriteStartAttribute(string prefix, string localName, string nsURI) {}
+
+		public override void WriteEndAttribute() {}
+
+		public override void WriteComment(string text) {}
+
+		public override void WriteProcessingInstruction(string name, string text) {}
+
+		public override void WriteString(string text) {
+			_writer.Write(text);
+		}
+
+		public override void WriteRaw(string data) {
+			_writer.Write(data);
+		}
+
+		public override void Close() {
+			_writer.Close();
+		}
+	}
+}

+ 98 - 0
mcs/class/System.XML/Mono.Xml.Xsl/XmlOutputter.cs

@@ -0,0 +1,98 @@
+//
+// XmlOutputter.cs
+//
+// Authors:
+//	Oleg Tkachenko ([email protected])
+//	
+// (C) 2003 Oleg Tkachenko
+//
+
+using System;
+using System.Xml;
+using System.IO;
+using System.Collections;
+
+namespace Mono.Xml.Xsl {
+	/// <summary>
+	/// Outputter implementation for XML output method
+	/// </summary>
+	public class XmlOutputter : Outputter {
+		private XmlWriter _writer;
+		private Hashtable _outputs;
+		private XslOutput _currentOutput;
+
+		public XmlOutputter(XmlWriter w, Hashtable o) {
+			_writer = w;
+			_outputs = o;
+			_currentOutput = (XslOutput)o[String.Empty];
+		}
+
+		public XmlOutputter(TextWriter w, Hashtable o)
+			: this(new XmlTextWriter(w), o) {}
+
+		public override void WriteStartDocument() {
+			if (_currentOutput != null && _currentOutput.OmitXmlDeclaration)
+				return;
+			if (_currentOutput == null || _currentOutput.Standalone == null)
+				_writer.WriteStartDocument();
+			else 
+				_writer.WriteStartDocument(_currentOutput.Standalone == "yes");		
+		}
+		
+		public override void WriteEndDocument() {
+			_writer.WriteEndDocument();		
+		}
+
+		public override void WriteStartElement(string localName, string nsURI) {
+			_writer.WriteStartElement(localName, nsURI);
+		}
+
+		public override void WriteStartElement(string prefix, string localName, string nsURI) {
+			_writer.WriteStartElement(prefix, localName, nsURI);
+		}
+
+		public override void WriteEndElement() {
+			_writer.WriteEndElement();
+		}
+
+		public override void WriteAttributeString(string localName, string value) {
+			_writer.WriteAttributeString(localName, value);
+		}
+
+		public override void WriteAttributeString(string prefix, string localName, string nsURI, string value) {
+			_writer.WriteAttributeString(prefix, localName, nsURI, value);
+		}
+
+		public override void WriteStartAttribute(string localName, string nsURI) {
+			_writer.WriteStartAttribute(localName, nsURI);
+		}
+
+		public override void WriteStartAttribute(string prefix, string localName, string nsURI) {
+			_writer.WriteStartAttribute(prefix, localName, nsURI);
+		}
+
+		public override void WriteEndAttribute() {
+			_writer.WriteEndElement();	
+		}
+
+		public override void WriteComment(string text) {
+			_writer.WriteComment(text);
+		}
+
+		public override void WriteProcessingInstruction(string name, string text) {
+			_writer.WriteProcessingInstruction(name, text);
+		}
+
+		public override void WriteString(string text) {
+			_writer.WriteString(text);
+		}
+
+		public override void WriteRaw(string data) {
+			_writer.WriteRaw(data);
+		}
+
+		public override void Close() {
+			_writer.Close();
+		}
+	}
+}

+ 43 - 14
mcs/class/System.XML/Mono.Xml.Xsl/XslOutput.cs

@@ -4,9 +4,11 @@
 // Authors:
 //	Ben Maurer ([email protected])
 //	Atsushi Enomoto ([email protected])
+//	Oleg Tkachenko ([email protected])
 //	
 // (C) 2003 Ben Maurer
 // (C) 2003 Atsushi Enomoto
+// (C) 2003 Oleg Tkachenko
 //
 
 using System;
@@ -21,10 +23,18 @@ namespace Mono.Xml.Xsl
 {
 	using QName = System.Xml.XmlQualifiedName;
 
+	public enum OutputMethod {
+		XML,
+		HTML,
+		Text,
+		Custom
+	}
+	
 	public class XslOutput	// also usable for xsl:result-document
 	{
 		string uri;
-		QName method;
+		QName customMethod;
+		OutputMethod method = OutputMethod.XML; 
 		string version;
 		string encoding;
 		bool omitXmlDeclaration;
@@ -48,9 +58,8 @@ namespace Mono.Xml.Xsl
 			this.uri = uri;
 		}
 
-		public QName Method {
-			get { return method; }
-		}
+		public OutputMethod Method { get { return method; }}
+		public QName CustomMethod { get { return customMethod; }}
 
 		public string Version {
 			get { return version; }
@@ -128,39 +137,59 @@ namespace Mono.Xml.Xsl
 		//		cdSectsList.AddRange (XslNameUtil.ParseQNames (att, nav));
 
 			att = nav.GetAttribute ("method", "");
-			if (att != null)
-				this.method = XslNameUtil.FromString (att, nav);
+
+			if (att != String.Empty) {
+				switch (att) {
+					case "xml":
+						method = OutputMethod.XML;
+						break;
+					case "html":
+						method = OutputMethod.HTML;
+						break;
+					case "text":
+						method = OutputMethod.Text;
+						break;
+					default:
+						method = OutputMethod.Custom;
+						customMethod = XslNameUtil.FromString (att, nav);
+						if (customMethod.Namespace == String.Empty)
+							//TODO: how to get current line number and position?
+							throw new XsltCompileException(new ArgumentException("Invalid output method value: '" + att + 
+							"'. It must be either 'xml' or 'html' or 'text' or QName."), nav.BaseURI, 1, 1);
+						break;
+				}
+			}
 
 			att = nav.GetAttribute ("version", "");
-			if (att != null)
+			if (att != String.Empty)
 				this.version = att;
 
 			att = nav.GetAttribute ("encoding", "");
-			if (att != null)
+			if (att != String.Empty)
 				this.encoding = att;
 
 			att = nav.GetAttribute ("standalone", "");
-			if (att != null)
+			if (att != String.Empty)
 				this.standalone = att;
 
 			att = nav.GetAttribute ("doctype-public", "");
-			if (att != null)
+			if (att != String.Empty)
 				this.doctypePublic = att;
 
 			att = nav.GetAttribute ("doctype-system", "");
-			if (att != null)
+			if (att != String.Empty)
 				this.doctypeSystem = att;
 
 			att = nav.GetAttribute ("media-type", "");
-			if (att != null)
+			if (att != String.Empty)
 				this.mediaType = att;
 
 			att = nav.GetAttribute ("omit-xml-declaration", "");
-			if (att != null)
+			if (att != String.Empty)
 				this.omitXmlDeclaration = att == "yes";
 
 			att = nav.GetAttribute ("indent", "");
-			if (att != null)
+			if (att != String.Empty)
 				this.indent = att == "yes";
 		}
 	}

+ 8 - 7
mcs/class/System.XML/Mono.Xml.Xsl/XslTransformProcessor.cs

@@ -20,7 +20,8 @@ using Mono.Xml.Xsl.Operations;
 using QName = System.Xml.XmlQualifiedName;
 
 namespace Mono.Xml.Xsl {
-	public class XslTransformProcessor {
+	public class XslTransformProcessor 
+	{
 		CompiledStylesheet compiledStyle;
 		
 		XslStylesheet style;
@@ -41,7 +42,7 @@ namespace Mono.Xml.Xsl {
 			this.style = style.Style;
 		}
 
-		public void Process (XPathNavigator root, XmlWriter output, XsltArgumentList args, XmlResolver resolver)
+		public void Process (XPathNavigator root, Outputter outputtter, XsltArgumentList args, XmlResolver resolver)
 		{
 			foreach (XslGlobalVariable v in CompiledStyle.Variables.Values)	{
 				if (v is XslGlobalParam) {
@@ -54,7 +55,7 @@ namespace Mono.Xml.Xsl {
 			this.args = args;
 			this.root = root;
 			this.resolver = resolver != null ? resolver : new XmlUrlResolver ();
-			this.outputStack.Push (output);
+			this.outputStack.Push (outputtter);
 			this.ApplyTemplates (root.Select ("."), QName.Empty, null);
 		}
 		
@@ -69,16 +70,16 @@ namespace Mono.Xml.Xsl {
 		#region Output
 		Stack outputStack = new Stack ();
 		
-		public XmlWriter Out { get { return (XmlWriter)outputStack.Peek(); }}
+		public Outputter Out { get { return (Outputter)outputStack.Peek(); }}
 		
-		public void PushOutput (XmlWriter newOutput)
+		public void PushOutput (Outputter newOutput)
 		{
 			this.outputStack.Push (newOutput);
 		}
 		
-		public XmlWriter PopOutput ()
+		public Outputter PopOutput ()
 		{
-			return (XmlWriter)this.outputStack.Pop ();
+			return (Outputter)this.outputStack.Pop ();
 		}
 		#endregion
 		

+ 4 - 0
mcs/class/System.XML/System.Xml.Xsl/ChangeLog

@@ -1,3 +1,7 @@
+2003-08-18 Ben Maurer  <[email protected]>
+
+	* *.cs: Support for xsl:output. (Oleg)
+
 2003-08-17 Ben Maurer  <[email protected]>
 
 	* XslTransformImpl.cs: close XmlTextWriter when we create it.

+ 25 - 3
mcs/class/System.XML/System.Xml.Xsl/ManagedXslTransform.cs

@@ -28,14 +28,36 @@ namespace System.Xml.Xsl {
 
 		public override void Transform (XPathNavigator input, XsltArgumentList args, XmlWriter output, XmlResolver resolver)
 		{
+			Outputter outputter = new XmlOutputter(output, s.Style.Outputs);
 			bool wroteStartDocument = false;
 			if (output.WriteState == WriteState.Start) {
-				output.WriteStartDocument ();
+				outputter.WriteStartDocument ();
 				wroteStartDocument = true;
 			}
-			new XslTransformProcessor (s).Process (input, output, args, resolver);
+			new XslTransformProcessor (s).Process (input, outputter, args, resolver);
 			if (wroteStartDocument)
-				output.WriteEndDocument ();
+				outputter.WriteEndDocument ();
+		}
+
+		public override void Transform (XPathNavigator input, XsltArgumentList args, TextWriter output, XmlResolver resolver) {
+			XslOutput xslOutput = (XslOutput)s.Style.Outputs[String.Empty];
+			if (xslOutput == null) {
+				//No xsl:output - subject to output method autodetection, XML for a while
+				Transform(input, args, new XmlTextWriter(output), resolver);
+				return;
+			}				
+			switch (xslOutput.Method) {
+				case OutputMethod.XML:
+					Transform(input, args, new XmlTextWriter(output), resolver);
+					break;
+				case OutputMethod.HTML:
+					throw new NotImplementedException("HTML output method is not implemented yet.");
+				case OutputMethod.Text:
+					new XslTransformProcessor (s).Process (input, new TextOutputter(output), args, resolver);
+					break;
+				case OutputMethod.Custom:
+					throw new NotImplementedException("Custom output method is not implemented yet.");
+			}
 		}
 	}
 }

+ 1 - 1
mcs/class/System.XML/System.Xml.Xsl/Multiplexer.cs

@@ -76,7 +76,7 @@ namespace System.Xml.Xsl {
 
 		public void Transform(XPathNavigator input, XsltArgumentList args, TextWriter output)
 		{
-			impl.Transform (input, args, new XmlTextWriter (output), xmlResolver);
+			impl.Transform (input, args, output, xmlResolver);
 		}
 		
 		public void Transform (string inputfile, string outputfile)

+ 4 - 0
mcs/class/System.XML/System.Xml.Xsl/XslTransform.cs

@@ -279,6 +279,10 @@ namespace System.Xml.Xsl
 			output.WriteRaw (writer.GetStringBuilder ().ToString ());
 			output.Flush ();
 		}
+		public override void Transform (XPathNavigator input, XsltArgumentList args, TextWriter output, XmlResolver resolver) 
+		{
+			Transform(input, args, new XmlTextWriter(output), resolver);
+		}
 
 		public override void Transform(string inputfile, string outputfile, XmlResolver resolver)
 		{

+ 4 - 4
mcs/class/System.XML/System.Xml.Xsl/XslTransformImpl.cs

@@ -32,12 +32,12 @@ namespace System.Xml.Xsl {
 
 		public abstract void Transform (XPathNavigator input, XsltArgumentList args, XmlWriter output, XmlResolver resolver);
 
+		public abstract void Transform (XPathNavigator input, XsltArgumentList args, TextWriter output, XmlResolver resolver);
+
 		public virtual void Transform (string inputfile, string outputfile, XmlResolver resolver)
 		{
-			using (FileStream fs =  new FileStream (outputfile, FileMode.Create, FileAccess.ReadWrite)) {
-				XmlTextWriter t = new XmlTextWriter (fs, null);
-				Transform(new XPathDocument (inputfile).CreateNavigator (), null, t, resolver);
-				t.Close ();
+			using (StreamWriter w = new StreamWriter (outputfile)) {
+				Transform(new XPathDocument (inputfile).CreateNavigator (), null, w, resolver);
 			}
 		}
 	}

+ 3 - 0
mcs/class/System.XML/System.Xml.dll.sources

@@ -26,6 +26,9 @@ Mono.Xml.Xsl.Operations/XslTemplateContent.cs
 Mono.Xml.Xsl.Operations/XslText.cs
 Mono.Xml.Xsl.Operations/XslValueOf.cs
 Mono.Xml.Xsl.Operations/XslVariable.cs
+Mono.Xml.Xsl/XmlOutputter.cs
+Mono.Xml.Xsl/Outputter.cs
+Mono.Xml.Xsl/TextOutputter.cs
 Mono.Xml.Xsl/Compiler.cs
 Mono.Xml.Xsl/Debug.cs
 Mono.Xml.Xsl/MSXslScriptManager.cs