2004-11-17 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / System.XML / Mono.Xml.Xsl.Operations / XslAttribute.cs
index 259b396d2aae77b3449900c7c402d1cdab78b5fb..09b2e6562e39551cca0748e58ea0b5af5986ca57 100644 (file)
@@ -9,6 +9,27 @@
 // (C) 2003 Atsushi Enomoto
 //
 
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
 using System;
 using System.Collections;
 using System.Xml;
@@ -19,7 +40,7 @@ using System.IO;
 using QName = System.Xml.XmlQualifiedName;
 
 namespace Mono.Xml.Xsl.Operations {
-       public class XslAttribute : XslCompiledElement {
+       internal class XslAttribute : XslCompiledElement {
                XslAvt name, ns;
                string calcName, calcNs, calcPrefix;
                XmlNamespaceManager nsm;
@@ -34,23 +55,47 @@ namespace Mono.Xml.Xsl.Operations {
                        nav = c.Input.Clone ();
                        
                        name = c.ParseAvtAttribute ("name");
+                       if (name == null)
+                               throw new XsltCompileException ("attribute \"name\" is required on XSLT attribute element.", null, c.Input);
                        ns = c.ParseAvtAttribute ("namespace");
 
                        calcName = XslAvt.AttemptPreCalc (ref name);
-                       
-                       if (calcName != null && ns == null) {
+                       calcPrefix = String.Empty;
+
+                       if (calcName != null) {
                                int colonAt = calcName.IndexOf (':');
                                calcPrefix = colonAt < 0 ? String.Empty : calcName.Substring (0, colonAt);
                                calcName = colonAt < 0 ? calcName : calcName.Substring (colonAt + 1, calcName.Length - colonAt - 1);
+
+                               try {
+                                       XmlConvert.VerifyNCName (calcName);
+                                       if (calcPrefix != String.Empty)
+                                               XmlConvert.VerifyNCName (calcPrefix);
+                               } catch (XmlException ex) {
+                                       throw new XsltCompileException ("Invalid attribute name.", ex, c.Input);
+                               }
+                       }
+                       if (calcPrefix != String.Empty && ns == null)
                                calcNs = nav.GetNamespace (calcPrefix);
-                       else if (ns != null)
+                       else if (ns != null)
                                calcNs = XslAvt.AttemptPreCalc (ref ns);
-                       
+
+                       if (calcNs ==null && calcPrefix != String.Empty) {
+                               string test = c.CurrentStylesheet.PrefixInEffect (calcPrefix, null);
+                               if (test != null) {
+                                       string alias = c.CurrentStylesheet.NamespaceAliases [calcPrefix] as string;
+                                       if (alias != null)
+                                               calcNs = c.Input.GetNamespace (alias);
+                                       else
+                                               calcNs = c.Input.NamespaceURI;
+                               }
+                       }
+
                        if (ns == null && calcNs == null)
                                nsm = c.GetNsm ();
                                
                        if (c.Input.MoveToFirstChild ()) {
-                               value = c.CompileTemplateContent ();
+                               value = c.CompileTemplateContent (XPathNodeType.Attribute);
                                c.Input.MoveToParent ();
                        }
 
@@ -58,7 +103,7 @@ namespace Mono.Xml.Xsl.Operations {
 
                public override void Evaluate (XslTransformProcessor p)
                {
-                       string nm, nmsp, localName, prefix;
+                       string nm, nmsp, prefix;
                        
                        nm = calcName != null ? calcName : name.Evaluate (p);
                        nmsp = calcNs != null ? calcNs : ns != null ? ns.Evaluate (p) : String.Empty;
@@ -71,9 +116,10 @@ namespace Mono.Xml.Xsl.Operations {
 
                        int colonAt = nm.IndexOf (':');
                        // local attribute
-                       prefix = colonAt < 0 ? String.Empty : nm.Substring (0, colonAt);
-                       nm = colonAt < 0 ? nm : nm.Substring (colonAt + 1, nm.Length - colonAt - 1);
                        if (colonAt > 0) {
+                               prefix = nm.Substring (0, colonAt);
+                               nm = nm.Substring (colonAt + 1, nm.Length - colonAt - 1);
+
                                // global attribute
                                if (nmsp == null) {
                                        QName q = XslNameUtil.FromString (nm, nsm);
@@ -98,6 +144,8 @@ namespace Mono.Xml.Xsl.Operations {
                        if (prefix == "xmlns")
                                prefix = String.Empty;  // Should not be allowed.
 
+                       XmlConvert.VerifyName (nm);
+
                        if (value == null)
                                p.Out.WriteAttributeString(prefix, nm, nmsp, "");
                        else {