2003-11-24 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 && ns == 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                                 calcNs = c.Input.GetNamespace (calcPrefix);
47                         } else if (ns != null)
48                                 calcNs = XslAvt.AttemptPreCalc (ref ns);
49                         
50                         if (ns == null && calcNs == null)
51                                 nsm = c.GetNsm ();
52                         
53                         useAttributeSets = c.ParseQNameListAttribute ("use-attribute-sets");
54                         
55                         isEmptyElement = c.Input.IsEmptyElement;
56
57                         if (c.Input.MoveToFirstChild ()) {
58                                 value = c.CompileTemplateContent ();
59                                 c.Input.MoveToParent ();
60                         }
61                 }
62                 
63                 public override void Evaluate (XslTransformProcessor p)
64                 {
65                         string nm, nmsp, localName, prefix;
66                         
67                         localName = nm = calcName != null ? calcName : name.Evaluate (p);
68                         nmsp = calcNs != null ? calcNs : ns != null ? ns.Evaluate (p) : null;
69
70                         if (nmsp == null) {
71                                 QName q = XslNameUtil.FromString (nm, nsm);
72                                 localName = q.Name;
73                                 nmsp = q.Namespace;
74                                 int colonAt = nm.IndexOf (':');
75                                 if (colonAt > 0)
76                                         calcPrefix = nm.Substring (0, colonAt);
77                         }
78                         prefix = calcPrefix != null ? calcPrefix : String.Empty;
79
80                         if (calcPrefix == String.Empty) {
81                                 if (nav.MoveToFirstNamespace (XPathNamespaceScope.ExcludeXml)) {
82                                         do {
83                                                 if (nav.Value == nmsp) {
84                                                         prefix = nav.Name;
85                                                         break;
86                                                 }
87                                         } while (nav.MoveToNextNamespace (XPathNamespaceScope.ExcludeXml));
88                                         nav.MoveToParent ();
89                                 }
90                         }
91
92                         XmlConvert.VerifyName (nm);
93
94                         bool cdataStarted = false;
95                         if (!p.InsideCDataElement && p.PushCDataState (localName, nmsp))
96                                 cdataStarted = true;
97                         p.Out.WriteStartElement (prefix, localName, nmsp);
98                         p.TryStylesheetNamespaceOutput (null);
99
100                         if (useAttributeSets != null)
101                                 foreach (XmlQualifiedName s in useAttributeSets)
102                                         p.ResolveAttributeSet (s).Evaluate (p);
103
104                         if (value != null) value.Evaluate (p);
105
106                         if (isEmptyElement && useAttributeSets == null)
107                                 p.Out.WriteEndElement ();
108                         else
109                                 p.Out.WriteFullEndElement ();
110                         if (cdataStarted)
111                                 p.PopCDataState ();
112                 }
113         }
114 }