2003-12-05 Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
[mono.git] / mcs / class / System.XML / Mono.Xml.Xsl.Operations / XslElement.cs
1 //
2 // XslElement.cs
3 //
4 // Authors:
5 //      Ben Maurer (bmaurer@users.sourceforge.net)
6 //      Atsushi Enomoto (ginga@kit.hi-ho.ne.jp)
7 //      
8 // (C) 2003 Ben Maurer
9 // (C) 2003 Atsushi Enomoto
10 //
11
12 using System;
13 using System.Collections;
14 using System.Xml;
15 using System.Xml.XPath;
16 using System.Xml.Xsl;
17
18 using QName = System.Xml.XmlQualifiedName;
19
20 namespace Mono.Xml.Xsl.Operations {     
21         public class XslElement : XslCompiledElement {
22                 XslAvt name, ns;
23                 string calcName, calcNs, calcPrefix;
24                 XmlNamespaceManager nsm;
25                 bool isEmptyElement;
26
27                 XslOperation value;
28                 XmlQualifiedName [] useAttributeSets;
29
30                 XPathNavigator nav;
31                 
32                 public XslElement (Compiler c) : base (c) {}
33                 protected override void Compile (Compiler c)
34                 {
35                         nav = c.Input.Clone ();
36
37                         name = c.ParseAvtAttribute ("name");
38                         ns = c.ParseAvtAttribute ("namespace");
39                         
40                         calcName = XslAvt.AttemptPreCalc (ref name);
41                         
42                         if (calcName != null) {
43                                 int colonAt = calcName.IndexOf (':');
44                                 calcPrefix = colonAt < 0 ? String.Empty : calcName.Substring (0, colonAt);
45                                 calcName = colonAt < 0 ? calcName : calcName.Substring (colonAt + 1, calcName.Length - colonAt - 1);
46                                 if (ns == null)
47                                         calcNs = c.Input.GetNamespace (calcPrefix);
48
49                                 try {
50                                         XmlConvert.VerifyNCName (calcName);
51                                         if (calcPrefix != String.Empty)
52                                                 XmlConvert.VerifyNCName (calcPrefix);
53                                 } catch (XmlException ex) {
54                                         throw new XsltCompileException ("Invalid attribute name.", ex, c.Input);
55                                 }
56                         } else if (ns != null)
57                                 calcNs = XslAvt.AttemptPreCalc (ref ns);
58                         
59                         if (ns == null && calcNs == null)
60                                 nsm = c.GetNsm ();
61                         
62                         useAttributeSets = c.ParseQNameListAttribute ("use-attribute-sets");
63                         
64                         isEmptyElement = c.Input.IsEmptyElement;
65
66                         if (c.Input.MoveToFirstChild ()) {
67                                 value = c.CompileTemplateContent (XPathNodeType.Element);
68                                 c.Input.MoveToParent ();
69                         }
70                 }
71                 
72                 public override void Evaluate (XslTransformProcessor p)
73                 {
74                         string nm, nmsp, localName, prefix;
75                         
76                         localName = nm = calcName != null ? calcName : name.Evaluate (p);
77                         nmsp = calcNs != null ? calcNs : ns != null ? ns.Evaluate (p) : null;
78
79                         if (nmsp == null) {
80                                 QName q = XslNameUtil.FromString (nm, nsm);
81                                 localName = q.Name;
82                                 nmsp = q.Namespace;
83                                 int colonAt = nm.IndexOf (':');
84                                 if (colonAt > 0)
85                                         calcPrefix = nm.Substring (0, colonAt);
86                         }
87                         prefix = calcPrefix != null ? calcPrefix : String.Empty;
88
89 #if false
90                         if (calcPrefix == String.Empty) {
91                                 if (nav.MoveToFirstNamespace (XPathNamespaceScope.ExcludeXml)) {
92                                         do {
93                                                 if (nav.Value == nmsp) {
94 //                                                      prefix = nav.Name;
95                                                         break;
96                                                 }
97                                         } while (nav.MoveToNextNamespace (XPathNamespaceScope.ExcludeXml));
98                                         nav.MoveToParent ();
99                                 }
100                         }
101 #endif
102
103                         XmlConvert.VerifyName (nm);
104
105                         bool isCData = p.InsideCDataElement;
106                         p.PushElementState (localName, nmsp, false);
107                         p.Out.WriteStartElement (prefix, localName, nmsp);
108                         p.TryStylesheetNamespaceOutput (null);
109
110                         if (useAttributeSets != null)
111                                 foreach (XmlQualifiedName s in useAttributeSets)
112                                         p.ResolveAttributeSet (s).Evaluate (p);
113
114                         if (value != null) value.Evaluate (p);
115
116                         if (isEmptyElement && useAttributeSets == null)
117                                 p.Out.WriteEndElement ();
118                         else
119                                 p.Out.WriteFullEndElement ();
120                         p.PopCDataState (isCData);
121                 }
122         }
123 }