2003-11-13 Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
authorAtsushi Eno <atsushieno@gmail.com>
Thu, 13 Nov 2003 02:18:06 +0000 (02:18 -0000)
committerAtsushi Eno <atsushieno@gmail.com>
Thu, 13 Nov 2003 02:18:06 +0000 (02:18 -0000)
* GenericOutputter.cs : Added HTML output support. Closer xmlns handling
  to Xalan tests and MS.NET implementation (only for test convenience).
* XslOutput.cs : Indent holds string rathen than bool. Its default value
  varies in the context. When method="html", then default is "yes".
* XslTransformProcessor.cs : Extension element prefixes should not
  be written as stylesheet namespaces.
* XsltCompiledContext.cs : Return type of generate-id() is string.
  Implemented unparsed-entity-uri().

svn path=/trunk/mcs/; revision=19928

mcs/class/System.XML/Mono.Xml.Xsl/ChangeLog
mcs/class/System.XML/Mono.Xml.Xsl/GenericOutputter.cs
mcs/class/System.XML/Mono.Xml.Xsl/HtmlEmitter.cs [new file with mode: 0644]
mcs/class/System.XML/Mono.Xml.Xsl/XslOutput.cs
mcs/class/System.XML/Mono.Xml.Xsl/XslTransformProcessor.cs
mcs/class/System.XML/Mono.Xml.Xsl/XsltCompiledContext.cs

index b9822da3feebfa1423144f1e1d06102c7807c2bf..48e476ca09be6d09ecae460f15db9e762eb05ee3 100644 (file)
@@ -1,3 +1,14 @@
+2003-11-13 Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
+
+       * GenericOutputter.cs : Added HTML output support. Closer xmlns handling
+         to Xalan tests and MS.NET implementation (only for test convenience).
+       * XslOutput.cs : Indent holds string rathen than bool. Its default value
+         varies in the context. When method="html", then default is "yes".
+       * XslTransformProcessor.cs : Extension element prefixes should not 
+         be written as stylesheet namespaces.
+       * XsltCompiledContext.cs : Return type of generate-id() is string.
+         Implemented unparsed-entity-uri().
+
 2003-11-02 Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
 
        * Compiler.cs : More complete attribute set gathering.
index 04c7e27ce82629233ffb818114cb55fa0104b4fe..9b053f0ddf0cd49f802b6ed90cd10f784ddc988d 100644 (file)
@@ -71,16 +71,14 @@ namespace Mono.Xml.Xsl
                                
                                case OutputMethod.HTML:
                                        Console.WriteLine ("WARNING: HTML output not fully supported, using XML output");
-                                       htmlEmulation = true;
-                                       goto case OutputMethod.XML;
+                                       _emitter = new HtmlEmitter (writer, xslOutput);
+                                       break;
                                case OutputMethod.Unknown: //TODO: handle xml vs html
                                case OutputMethod.XML:
                                        //TODO: XmlTextEmitter goes here
                                        //_emitter = new XmlTextEmitter (writer);
                                        XmlTextWriter w = new XmlTextWriter (writer);
-                                       if (_currentOutput.Indent)
-                                               w.Formatting = Formatting.Indented;
-                                       if (htmlEmulation)
+                                       if (xslOutput.Indent == "yes")
                                                w.Formatting = Formatting.Indented;
                                        _emitter = new XmlWriterEmitter (w);                                    
                                        break;
@@ -141,6 +139,7 @@ namespace Mono.Xml.Xsl
                        _emitter.WriteEndDocument ();                           
                }
 
+               int _nsCount;
                public override void WriteStartElement (string prefix, string localName, string nsURI)
                {
                        if (_state == WriteState.Prolog) {
@@ -179,7 +178,15 @@ namespace Mono.Xml.Xsl
                }
 
                public override void WriteAttributeString (string prefix, string localName, string nsURI, string value)
-               {                                                                               
+               {
+                       if (prefix == String.Empty && nsURI != String.Empty) {
+                               prefix = "xp_" + _nsCount;
+                               _nsManager.AddNamespace (prefix, nsURI);
+                               _currentNsPrefixes.Add (prefix);
+                               _currentNamespaceDecls.Add (prefix, nsURI);
+                               _nsCount++;
+                       }
+
                        //Put attribute to pending attributes collection, replacing namesake one
                        for (int i = 0; i < pendingAttributesPos; i++) {
                                Attribute attr = pendingAttributes [i];
diff --git a/mcs/class/System.XML/Mono.Xml.Xsl/HtmlEmitter.cs b/mcs/class/System.XML/Mono.Xml.Xsl/HtmlEmitter.cs
new file mode 100644 (file)
index 0000000..caa853c
--- /dev/null
@@ -0,0 +1,278 @@
+//
+// HtmlEmitter.cs
+//
+// Author:
+//     Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
+//     
+// (C)2003 Atsushi Enomoto
+//
+// TODO:
+//     indent, uri escape, allowed entity char such as &nbsp;,
+//     encoding to meta tag, doctype-public/doctype-system.
+//
+
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+using System.Xml;
+
+namespace Mono.Xml.Xsl
+{
+       public class HtmlEmitter : Emitter {
+               TextWriter writer;
+               Stack elementNameStack;
+               bool openElement;
+               bool openAttribute;
+               int xmlDepth;
+               bool indent;
+
+               public HtmlEmitter (TextWriter writer, XslOutput output)
+               {
+                       this.writer = writer;
+                       indent = !(output.Indent == "no");
+                       elementNameStack = new Stack ();
+                       xmlDepth = -1;
+               }
+
+               public override void WriteStartDocument (StandaloneType standalone)
+               {
+                       // do nothing
+               }
+               
+               public override void WriteEndDocument ()
+               {
+                       // do nothing
+               }
+
+               public override void WriteDocType (string name, string publicId, string systemId)
+               {
+                       writer.Write ("<!DOCTYPE ");
+                       writer.Write (name);
+                       writer.Write (' ');
+                       if (publicId != null && publicId != String.Empty) {
+                               writer.Write ("PUBLIC ");
+                               writer.Write (publicId);
+                               writer.Write (' ');
+                               writer.Write (systemId);
+                       } else if (systemId != null && systemId != String.Empty) {
+                               writer.Write ("SYSTEM ");
+                               writer.Write (systemId);
+                       }
+                       writer.Write ('>');
+               }
+
+               private void CloseAttribute ()
+               {
+                       writer.Write ('\"');
+                       openAttribute = false;
+               }
+
+               private void CloseStartElement ()
+               {
+                       if (openAttribute)
+                               CloseAttribute ();
+                       writer.Write ('>');
+                       openElement = false;
+               }
+
+               private void Indent (string elementName, bool alwaysOutputNewLine)
+               {
+                       if (!indent)
+                               return;
+                       switch (elementName.ToUpper ()) {
+                       case "FORM":
+                               return;
+                       }
+                       if (alwaysOutputNewLine || elementNameStack.Count > 0)
+                               writer.Write ("\r\n");
+                       for (int i = 0; i < elementNameStack.Count; i++)
+                                       writer.Write ("  ");
+               }
+
+               public override void WriteStartElement (string prefix, string localName, string nsURI)
+               {
+                       if (openElement)
+                               CloseStartElement ();
+                       Indent (elementNameStack.Count > 0 ? elementNameStack.Peek () as string : String.Empty, false);
+                       string formatName = localName;
+
+                       writer.Write ('<');
+                       if (nsURI != String.Empty) {
+                               // XML output
+                               if (prefix != String.Empty) {
+                                       writer.Write (prefix);
+                                       writer.Write (':');
+                                       formatName = String.Concat (prefix, ":", localName);
+                               }
+                               // TODO: handle xmlns using namespaceManager
+                               
+                               if (xmlDepth < 0)
+                                       xmlDepth = elementNameStack.Count + 1;
+                       }
+                       writer.Write (formatName);
+                       elementNameStack.Push (formatName);
+                       openElement = true;
+               }
+
+               public override void WriteEndElement ()
+               {
+                       WriteFullEndElement ();
+               }
+
+               public override void WriteFullEndElement ()
+               {
+                       string element = elementNameStack.Pop () as string;
+
+                       switch (element.ToUpper ()) {
+                       case "AREA":
+                       case "BASE":
+                       case "BASEFONT":
+                       case "BR":
+                       case "COL":
+                       case "FRAME":
+                       case "HR":
+                       case "IMAGE":
+                       case "INPUT":
+                       case "ISINDEX":
+                       case "LINK":
+                       case "META":
+                       case "PARAM":
+                               if (openAttribute)
+                                       CloseAttribute ();
+                               writer.Write ('>');
+                               break;
+                       default:
+                               if (openElement)
+                                       CloseStartElement ();
+                               Indent (element, true);
+                               writer.Write ("</");
+                               writer.Write (element);
+                               writer.Write (">");
+                               break;
+                       }
+                       openElement = false;
+
+                       if (xmlDepth > elementNameStack.Count)
+                               xmlDepth = -1;
+               }
+
+               public override void WriteAttributeString (string prefix, string localName, string nsURI, string value)
+               {
+                       if (xmlDepth >= 0) {
+                               writer.Write (' ');
+                               writer.Write (localName);
+                               writer.Write ("=\"");
+                               openAttribute = true;
+                               WriteFormattedString (value);
+                               openAttribute = false;
+                               writer.Write ('\"');
+                       }
+
+                       string attribute = localName.ToUpper ();
+                       writer.Write (' ');
+                       writer.Write (localName);
+
+                       switch (attribute) {
+                       case "OPTION":
+                       case "CHECKED":
+                               return;
+                       }
+
+                       writer.Write ("=\"");
+                       openAttribute = true;
+                       WriteFormattedString (value);
+                       openAttribute = false;
+                       writer.Write ('\"');
+               }
+
+               public override void WriteComment (string text) {
+                       writer.Write ("<!--");
+                       writer.Write (text);
+                       writer.Write ("-->");
+               }
+
+               public override void WriteProcessingInstruction (string name, string text)
+               {
+                       writer.Write ("<?");
+                       writer.Write (name);
+                       if (text != null && text != String.Empty) {
+                               writer.Write (' ');
+                               writer.Write (text);
+                       }
+
+                       if (xmlDepth >= 0)
+                               writer.Write ("?>");
+                       else
+                               writer.Write (">"); // HTML PI ends with '>'
+               }
+
+               public override void WriteString (string text)
+               {
+                       if (openElement)
+                               CloseStartElement ();
+                       WriteFormattedString (text);
+               }
+
+               private void WriteFormattedString (string text)
+               {
+                       // style and script should not be escaped.
+                       if (!openAttribute) {
+                               string element = ((string) elementNameStack.Peek ()).ToUpper ();
+                               switch (element) {
+                               case "SCRIPT":
+                               case "STYLE":
+                                       writer.Write (text);
+                                       return;
+                               }
+                       }
+
+                       int start = 0;
+                       for (int i = 0; i < text.Length; i++) {
+                               switch (text [i]) {
+                               case '&':
+                                       // '&' '{' should be "&{", not "&amp;{"
+                                       if (xmlDepth < 0 && i + 1 < text.Length && text [i + 1] == '{')
+                                               continue;
+                                       writer.Write (text.ToCharArray (), start, i - start);
+                                       writer.Write ("&amp;");
+                                       start = i;
+                                       break;
+                               case '<':
+                                       if (openAttribute)
+                                               continue;
+                                       writer.Write (text.ToCharArray (), start, i - start);
+                                       writer.Write ("&lt;");
+                                       start = i;
+                                       break;
+                               case '>':
+                                       writer.Write (text.ToCharArray (), start, i - start);
+                                       writer.Write ("&gt;");
+                                       start = i;
+                                       break;
+                               case '\'':
+                                       writer.Write (text.ToCharArray (), start, i - start);
+                                       writer.Write ("&apos;");
+                                       start = i;
+                                       break;
+                               case '\"':
+                                       writer.Write (text.ToCharArray (), start, i - start);
+                                       writer.Write ("&quot;");
+                                       start = i;
+                                       break;
+                               }
+                       }
+                       writer.Write (text.ToCharArray (), start, text.Length - start);
+               }
+
+               public override void WriteRaw (string data)
+               {
+                       writer.Write (data);
+               }
+
+               public override void Done ()
+               {
+                       writer.Flush ();
+               }
+       }
+}
index 5c23c7dc51cd0c6ae2748d01671512e44877d29d..39eb4d65959f8f06c9c3113c6d3a626e7c1c6a2e 100644 (file)
@@ -50,7 +50,7 @@ namespace Mono.Xml.Xsl
                string doctypePublic;
                string doctypeSystem;
                QName [] cdataSectionElements;
-               bool indent;
+               string indent;
                string mediaType;
                bool escapeUriAttributes;
                bool includeContentType;
@@ -105,7 +105,7 @@ namespace Mono.Xml.Xsl
                        }
                }
 
-               public bool Indent {
+               public string Indent {
                        get { return indent; }
                }
 
@@ -200,7 +200,7 @@ namespace Mono.Xml.Xsl
 
                        att = nav.GetAttribute ("indent", "");
                        if (att != String.Empty)
-                               this.indent = att == "yes";
+                               this.indent = att;
                }
        }
 
index 16655c006c37c0171d5e85fe580c288e3834d8da..def4b4c784d29a0ea535e77602a9d0c9e49fe9ad 100644 (file)
@@ -96,7 +96,7 @@ namespace Mono.Xml.Xsl {
                        }
 
                        XmlReader rdr = new XmlTextReader (uri.ToString(), (Stream) resolver.GetEntity (uri, null, null));
-                       result = new XPathDocument (rdr).CreateNavigator ();
+                       result = new XPathDocument (rdr, XmlSpace.Preserve).CreateNavigator ();
                        rdr.Close ();
                        
                        docCache [uri] = result.Clone ();
@@ -273,6 +273,16 @@ namespace Mono.Xml.Xsl {
                                                if (exclude)
                                                        continue;
                                        }
+                                       if (style.ExtensionElementPrefixes != null) {
+                                               bool exclude = false;
+                                               foreach (XmlQualifiedName exc in style.ExtensionElementPrefixes)
+                                                       if (exc.Name == "#default" && prefix == String.Empty || exc.Name == prefix) {
+                                                               exclude = true;
+                                                               break;
+                                                       }
+                                               if (exclude)
+                                                       continue;
+                                       }
                                        Out.WriteNamespaceDecl (prefix, this.style.StylesheetNamespaces [prefix]);
                                }
                                outputStylesheetXmlns = false;
index 7c1e4769a603fd108be20ac4452012bed611f04a..20a4341852715ff10828868e45c0c6247f232c03 100644 (file)
@@ -506,7 +506,7 @@ namespace Mono.Xml.Xsl.Functions {
                        }
                }
                
-               public override XPathResultType ReturnType { get { return XPathResultType.NodeSet; }}
+               public override XPathResultType ReturnType { get { return XPathResultType.String; }}
                public override object Evaluate (BaseIterator iter)
                {
                        XPathNavigator n;
@@ -661,7 +661,18 @@ namespace Mono.Xml.Xsl.Functions {
                public override XPathResultType ReturnType { get { return XPathResultType.String; }}
                public override object Evaluate (BaseIterator iter)
                {
-                       throw new NotImplementedException ();
+                       IHasXmlNode xn = iter.Current as IHasXmlNode;
+                       if (xn == null)
+                               return String.Empty;
+                       XmlNode n = xn.GetNode ();
+                       XmlDocumentType doctype = n.OwnerDocument.DocumentType;
+                       if (doctype == null)
+                               return String.Empty;
+                       XmlEntity ent = doctype.Entities.GetNamedItem (arg0.EvaluateString (iter)) as XmlEntity;
+                       if (ent == null)
+                               return String.Empty;
+                       else
+                               return ent.BaseURI;
                }
        }
 }
\ No newline at end of file