2003-11-02 Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
authorAtsushi Eno <atsushieno@gmail.com>
Sun, 2 Nov 2003 14:25:15 +0000 (14:25 -0000)
committerAtsushi Eno <atsushieno@gmail.com>
Sun, 2 Nov 2003 14:25:15 +0000 (14:25 -0000)
* Compiler.cs : More complete attribute set gathering.
  GetNamespacesToCopy() should only return Local namespaces.
* GenericOutputter.cs : Added support for indentation.
  Added easy hack for html output.
  More correct Prefix handling (considers already defined ones).
  Namespace emmission is moved to CheckState().
* Emitter.cs, XmlWriterEmitter.cs, GenericOutputter.cs, Outputter.cs :
  Added WriteFullEndElement(). (i.e. IsEmptyElement support)
* GenericOutputter.cs, Outputter.cs :
  Added CanProcessAttributes property for
  use-attribute-sets of xsl:copy.
* XslStylesheet.cs : Added support for stylesheet-defined xmlns decls.
  Added support for exclude-result-prefixes.
* XslTransformProcessor.cs : Added support for stylesheet-defined xmlns.

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

mcs/class/System.XML/Mono.Xml.Xsl/ChangeLog
mcs/class/System.XML/Mono.Xml.Xsl/Compiler.cs
mcs/class/System.XML/Mono.Xml.Xsl/Emitter.cs
mcs/class/System.XML/Mono.Xml.Xsl/GenericOutputter.cs
mcs/class/System.XML/Mono.Xml.Xsl/Outputter.cs
mcs/class/System.XML/Mono.Xml.Xsl/XmlWriterEmitter.cs
mcs/class/System.XML/Mono.Xml.Xsl/XslStylesheet.cs
mcs/class/System.XML/Mono.Xml.Xsl/XslTransformProcessor.cs

index 14d267e1c8e10f21f3325fe50adde93413aa5e01..b9822da3feebfa1423144f1e1d06102c7807c2bf 100644 (file)
@@ -1,3 +1,20 @@
+2003-11-02 Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
+
+       * Compiler.cs : More complete attribute set gathering.
+         GetNamespacesToCopy() should only return Local namespaces.
+       * GenericOutputter.cs : Added support for indentation.
+         Added easy hack for html output.
+         More correct Prefix handling (considers already defined ones).
+         Namespace emmission is moved to CheckState().
+       * Emitter.cs, XmlWriterEmitter.cs, GenericOutputter.cs, Outputter.cs :
+         Added WriteFullEndElement(). (i.e. IsEmptyElement support)
+       * GenericOutputter.cs, Outputter.cs :
+         Added CanProcessAttributes property for 
+         use-attribute-sets of xsl:copy.
+       * XslStylesheet.cs : Added support for stylesheet-defined xmlns decls.
+         Added support for exclude-result-prefixes.
+       * XslTransformProcessor.cs : Added support for stylesheet-defined xmlns.
+
 2003-10-30 Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
 
        * Compiler.cs : It is not important, but attribute order became closer
index 0206df6bbb99a36c9d6b4230097799cca2c8ce2c..9f68f44acc0a395deeb155cfd86010252b769afb 100644 (file)
@@ -291,9 +291,12 @@ namespace Mono.Xml.Xsl {
                {
                        XslAttributeSet existing = attrSets [set.Name] as XslAttributeSet;
                        // The latter set will have higher priority
-                       if (existing != null)
+                       if (existing != null) {
                                existing.Merge (set);
-                       attrSets [set.Name] = set;
+                               attrSets [set.Name] = existing;
+                       }
+                       else
+                               attrSets [set.Name] = set;
                }
                
                VariableScope curVarScope;
@@ -362,11 +365,11 @@ namespace Mono.Xml.Xsl {
                        XPathNavigator nav = Input.Clone ();
                        XPathNavigator nsScope = nav.Clone ();
                        
-                       if (nav.MoveToFirstNamespace (XPathNamespaceScope.ExcludeXml)) {
+                       if (nav.MoveToFirstNamespace (XPathNamespaceScope.Local)) {
                                do {
                                        if (nav.Value != XsltNamespace && !ret.Contains (nav.Name))
                                                ret.Add (nav.Name, nav.Value);
-                               } while (nav.MoveToNextNamespace (XPathNamespaceScope.ExcludeXml));
+                               } while (nav.MoveToNextNamespace (XPathNamespaceScope.Local));
                                nav.MoveToParent ();
                        }
                        
index 54f60fa690c9106c056857bef06d0dd6d0612a91..68141bfd19adc4e5edbb69eac4de1b8db15b869b 100644 (file)
@@ -21,7 +21,12 @@ namespace Mono.Xml.Xsl {
                public abstract void WriteEndDocument ();                                               
                public abstract void WriteDocType (string type, string publicId, string systemId);
                public abstract void WriteStartElement (string prefix, string localName, string nsURI);
-               public abstract void WriteEndElement ();                                                
+               public abstract void WriteEndElement ();
+               public virtual void WriteFullEndElement ()
+               {
+                       WriteEndElement ();
+               }
+
                public abstract void WriteAttributeString (string prefix, string localName, string nsURI, string value);                                        
                public abstract void WriteComment (string text);                
                public abstract void WriteProcessingInstruction (string name, string text);             
index d3466a595709a4f59774e5e9a3b9e8ee4b6b40db..04c7e27ce82629233ffb818114cb55fa0104b4fe 100644 (file)
@@ -3,8 +3,9 @@
 //
 // Authors:
 //     Oleg Tkachenko (oleg@tkachenko.com)
+//     Atsushi Enomoto (ginga@kit.hi-ho.ne.jp)
 //     
-// (C) 2003 Oleg Tkachenko
+// (C) 2003 Oleg Tkachenko, Atsushi Enomoto
 //
 
 using System;
@@ -35,9 +36,15 @@ namespace Mono.Xml.Xsl
                int pendingAttributesPos = 0;
                //Namespace manager. Subject to optimization.
                private XmlNamespaceManager _nsManager;
+               private ArrayList _currentNsPrefixes;
+               private Hashtable _currentNamespaceDecls;
                //Name table
                private NameTable _nt;
-               
+               //Determines whether xsl:copy can output attribute-sets or not.
+               bool canProcessAttributes;
+               // FIXME: This is quick hack to eliminate XML declaration for HTML output.
+               bool htmlEmulation;
+
                private GenericOutputter (Hashtable outputs)
                {
                        _outputs = outputs;
@@ -46,6 +53,8 @@ namespace Mono.Xml.Xsl
                        //TODO: Optimize using nametable
                        _nt = new NameTable ();
                        _nsManager = new XmlNamespaceManager (_nt);
+                       _currentNsPrefixes = new ArrayList ();
+                       _currentNamespaceDecls = new Hashtable ();
                }
 
                public GenericOutputter (XmlWriter writer, Hashtable outputs) 
@@ -62,12 +71,18 @@ namespace Mono.Xml.Xsl
                                
                                case OutputMethod.HTML:
                                        Console.WriteLine ("WARNING: HTML output not fully supported, using XML output");
+                                       htmlEmulation = true;
                                        goto case OutputMethod.XML;
                                case OutputMethod.Unknown: //TODO: handle xml vs html
                                case OutputMethod.XML:
                                        //TODO: XmlTextEmitter goes here
                                        //_emitter = new XmlTextEmitter (writer);
-                                       _emitter = new XmlWriterEmitter (new XmlTextWriter (writer));                                   
+                                       XmlTextWriter w = new XmlTextWriter (writer);
+                                       if (_currentOutput.Indent)
+                                               w.Formatting = Formatting.Indented;
+                                       if (htmlEmulation)
+                                               w.Formatting = Formatting.Indented;
+                                       _emitter = new XmlWriterEmitter (w);                                    
                                        break;
                                case OutputMethod.Text:
                                        _emitter = new TextEmitter (writer);
@@ -91,18 +106,31 @@ namespace Mono.Xml.Xsl
                                //Emit pending attributes
                                for (int i = 0; i < pendingAttributesPos; i++) {
                                        Attribute attr = pendingAttributes [i];
-                                       _emitter.WriteAttributeString (attr.Prefix, attr.LocalName, attr.Namespace, attr.Value);
-                               }       
+                                       string prefix = _nsManager.LookupPrefix (attr.Namespace);
+                                       if (prefix == null)
+                                               prefix = attr.Prefix;
+                                       _emitter.WriteAttributeString (prefix, attr.LocalName, attr.Namespace, attr.Value);
+                               }
+                               foreach (string prefix in _currentNsPrefixes) {
+                                       string uri = _currentNamespaceDecls [prefix] as string;
+                                       if (prefix != String.Empty)
+                                               _emitter.WriteAttributeString ("xmlns", prefix, XmlNamespaceManager.XmlnsXmlns, uri);
+                                       else
+                                               _emitter.WriteAttributeString (String.Empty, "xmlns", XmlNamespaceManager.XmlnsXmlns, uri);
+                               }
+                               _currentNsPrefixes.Clear ();
+                               _currentNamespaceDecls.Clear ();
                                //Attributes flushed, state is Content now                              
                                _state = WriteState.Content;
-                       }               
+                       }
+                       canProcessAttributes = false;
                }
 
                #region Outputter's methods implementation
                
                public override void WriteStartDocument ()
                {                       
-                       if (!_currentOutput.OmitXmlDeclaration)
+                       if (!_currentOutput.OmitXmlDeclaration && !htmlEmulation)
                                _emitter.WriteStartDocument (_currentOutput.Standalone);
                        
                        _state = WriteState.Prolog;
@@ -125,12 +153,26 @@ namespace Mono.Xml.Xsl
                        _emitter.WriteStartElement (prefix, localName, nsURI);
                        _state = WriteState.Element;                                            
                        pendingAttributesPos = 0;
+                       canProcessAttributes = true;
                }
 
                public override void WriteEndElement ()
+               {
+                       WriteEndElementInternal (false);
+               }
+
+               public override void WriteFullEndElement()
+               {
+                       WriteEndElementInternal (true);
+               }
+
+               private void WriteEndElementInternal (bool fullEndElement)
                {
                        CheckState ();
-                       _emitter.WriteEndElement ();
+                       if (fullEndElement)
+                               _emitter.WriteFullEndElement ();
+                       else
+                               _emitter.WriteEndElement ();
                        _state = WriteState.Content;
                        //Pop namespace scope
                        _nsManager.PopScope ();
@@ -147,7 +189,6 @@ namespace Mono.Xml.Xsl
                                        //Keep prefix (e.g. when literal attribute is overriden by xsl:attribute)
                                        if (attr.Prefix == String.Empty && prefix != String.Empty)
                                                pendingAttributes [i].Prefix = prefix;
-                                       
                                        return;
                                }
                        }
@@ -169,15 +210,16 @@ namespace Mono.Xml.Xsl
                {
                        if (prefix == String.Empty) {
                                //Default namespace
-                               if (_nsManager.DefaultNamespace != nsUri) {
+                               if (_nsManager.DefaultNamespace != nsUri)
                                        _nsManager.AddNamespace (prefix, nsUri);
-                                       _emitter.WriteAttributeString ("", "xmlns", "", nsUri);
-                               }
-                       } else if (_nsManager.LookupPrefix (nsUri) == null) {
-                               //That's new namespace - add it to the collection and emit
+                       } else if (_nsManager.LookupPrefix (nsUri) == null)
+                               //That's new namespace - add it to the collection
                                _nsManager.AddNamespace (prefix, nsUri);
-                               _emitter.WriteAttributeString ("xmlns", prefix, null, nsUri);
-                       }                       
+
+                       if (_currentNamespaceDecls [prefix] as string != nsUri) {
+                               _currentNsPrefixes.Add (prefix);
+                               _currentNamespaceDecls [prefix] = nsUri;
+                       }
                }
                                        
                public override void WriteComment (string text)
@@ -209,6 +251,10 @@ namespace Mono.Xml.Xsl
                        _emitter.Done ();
                        _state = WriteState.Closed;
                }
+
+               public override bool CanProcessAttributes {
+                       get { return canProcessAttributes; }
+               }
                #endregion
        }
 }
index d1429d072e4f2754c8bedc863df4846e02b5c622..3ce2d190451d9cbafb78eaff84fd35b8972a20a1 100644 (file)
@@ -27,6 +27,10 @@ namespace Mono.Xml.Xsl {
                
                public abstract void WriteStartElement (string prefix, string localName, string nsURI);
                public abstract void WriteEndElement ();
+               public virtual void WriteFullEndElement ()
+               {
+                       WriteEndElement ();
+               }
                
                public void WriteAttributeString (string localName, string value)
                {
@@ -44,5 +48,9 @@ namespace Mono.Xml.Xsl {
                public abstract void WriteRaw (string data);
                
                public abstract void Done ();
+
+               public virtual bool CanProcessAttributes {
+                       get { return false; }
+               }
        }
 }
index fbc0317b6f6b9cadbb0d483d93f5a93522ac91fb..1babbbd7d4f81aadd04fca1bf65f81446fefbbf9 100644 (file)
@@ -51,6 +51,11 @@ namespace Mono.Xml.Xsl {
                        writer.WriteEndElement ();
                }
 
+               public override void WriteFullEndElement ()
+               {
+                       writer.WriteFullEndElement ();
+               }
+
                public override void WriteAttributeString (string prefix, string localName, string nsURI, string value)
                {
                        writer.WriteAttributeString (prefix, localName, nsURI, value);
index e4e6290202736bebab4f7e22de0efba44fd90c1e..acd011c64ecca366c5725718cb6cb6cd10b07538 100644 (file)
@@ -48,6 +48,7 @@ namespace Mono.Xml.Xsl {
                string version;\r
                XmlQualifiedName [] extensionElementPrefixes;\r
                XmlQualifiedName [] excludeResultPrefixes;\r
+               StringDictionary stylesheetNamespaces = new StringDictionary ();\r
 \r
                // below are newly introduced in XSLT 2.0\r
                //  elements::\r
@@ -65,6 +66,18 @@ namespace Mono.Xml.Xsl {
                string xpathDefaultNamespace = "";\r
                XslDefaultValidation defaultValidation = XslDefaultValidation.Lax;\r
 \r
+               public XmlQualifiedName [] ExtensionElementPrefixes {\r
+                       get { return extensionElementPrefixes; }\r
+               }\r
+\r
+               public XmlQualifiedName [] ExcludeResultPrefixes {\r
+                       get { return excludeResultPrefixes; }\r
+               }\r
+\r
+               public StringDictionary StylesheetNamespaces {\r
+                       get { return stylesheetNamespaces; }\r
+               }\r
+\r
                public ArrayList Imports {\r
                        get { return imports; }\r
                }\r
@@ -103,7 +116,14 @@ namespace Mono.Xml.Xsl {
                                version = c.Input.GetAttribute ("version", "");\r
                                extensionElementPrefixes = c.ParseQNameListAttribute ("extension-element-prefixes");\r
                                excludeResultPrefixes = c.ParseQNameListAttribute ("exclude-result-prefixes");\r
-                               
+                               if (c.Input.MoveToFirstNamespace (XPathNamespaceScope.Local)) {
+                                       do {
+                                               if (c.Input.Value == XsltNamespace)
+                                                       continue;
+                                               this.stylesheetNamespaces.Add (c.Input.Name, c.Input.Value);
+                                       } while (c.Input.MoveToNextNamespace (XPathNamespaceScope.Local));
+                                       c.Input.MoveToParent ();
+                               }
                                ProcessTopLevelElements ();\r
                        }
                        
index d0c486da1d42058aa730767c788134544eb3e8ce..16655c006c37c0171d5e85fe580c288e3834d8da 100644 (file)
@@ -33,6 +33,7 @@ namespace Mono.Xml.Xsl {
                XsltContext ctx;
                XsltArgumentList args;
                XmlResolver resolver;
+               bool outputStylesheetXmlns;
                
                internal readonly XsltCompiledContext XPathContext;
 
@@ -51,7 +52,8 @@ namespace Mono.Xml.Xsl {
                        this.args = args;
                        this.root = root;
                        this.resolver = resolver != null ? resolver : new XmlUrlResolver ();
-                       
+                       this.outputStylesheetXmlns = true;
+
                        PushNodeset (root.Select ("."));
                        
                        foreach (XslGlobalVariable v in CompiledStyle.Variables.Values) {
@@ -256,6 +258,26 @@ namespace Mono.Xml.Xsl {
                        t.Evaluate (this);
                        currentTemplateStack.Pop ();
                }
+
+               internal void TryStylesheetNamespaceOutput ()
+               {
+                       if (outputStylesheetXmlns) {
+                               foreach (string prefix in this.style.StylesheetNamespaces.Keys) {
+                                       if (style.ExcludeResultPrefixes != null) {
+                                               bool exclude = false;
+                                               foreach (XmlQualifiedName exc in style.ExcludeResultPrefixes)
+                                                       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;
+                       }
+               }
                
                XslTemplate FindTemplate (XPathNavigator node, QName mode)
                {