2004-04-24 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / System.XML / Mono.Xml.Xsl.Operations / XslCopy.cs
1 //
2 // XslCopy.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 namespace Mono.Xml.Xsl.Operations {
19         internal class XslCopy : XslCompiledElement {
20                 XslOperation children;
21                 XmlQualifiedName [] useAttributeSets;
22                 
23                 public XslCopy (Compiler c) : base (c) {}
24                 
25                 protected override void Compile (Compiler c)
26                 {
27                         if (c.Input.MoveToFirstAttribute ()) {
28                                 do {
29                                         if (c.Input.NamespaceURI == String.Empty && c.Input.LocalName != "use-attribute-sets")
30                                                 throw new XsltCompileException ("Unrecognized attribute \"" + c.Input.Name + "\" in XSLT copy element.", null, c.Input);
31                                 } while (c.Input.MoveToNextAttribute ());
32                                 c.Input.MoveToParent ();
33                         }
34
35                         useAttributeSets = c.ParseQNameListAttribute ("use-attribute-sets");
36                         
37                         if (!c.Input.MoveToFirstChild ()) return;
38                         children = c.CompileTemplateContent();
39                         c.Input.MoveToParent ();
40                 }
41
42                 public override void Evaluate (XslTransformProcessor p)
43                 {
44                         switch (p.CurrentNode.NodeType)
45                         {
46                         case XPathNodeType.Root:
47                                 if (p.Out.CanProcessAttributes && useAttributeSets != null)
48                                         foreach (XmlQualifiedName s in useAttributeSets) {
49                                                 XslAttributeSet attset = p.ResolveAttributeSet (s);
50                                                 if (attset == null)
51                                                         throw new XsltException ("Attribute set was not found.", null, p.CurrentNode);
52                                                 attset.Evaluate (p);
53                                         }
54
55                                 if (children != null) children.Evaluate (p);
56                                 break;
57                         case XPathNodeType.Element:
58                                 bool isCData = p.InsideCDataElement;
59                                 p.PushElementState (p.CurrentNode.LocalName, p.CurrentNode.NamespaceURI, true);
60                                 p.Out.WriteStartElement (p.CurrentNode.Prefix, p.CurrentNode.LocalName, p.CurrentNode.NamespaceURI);
61                                 
62                                 p.TryStylesheetNamespaceOutput (null);
63                                 if (useAttributeSets != null)
64                                         foreach (XmlQualifiedName s in useAttributeSets)
65                                                 p.ResolveAttributeSet (s).Evaluate (p);
66
67                                 if (p.CurrentNode.MoveToFirstNamespace (XPathNamespaceScope.Local)) {
68                                         do {
69                                                 p.Out.WriteNamespaceDecl (p.CurrentNode.LocalName, p.CurrentNode.Value);
70                                         } while (p.CurrentNode.MoveToNextNamespace (XPathNamespaceScope.Local));
71                                         p.CurrentNode.MoveToParent ();
72                                 }
73                         
74                                 if (children != null) children.Evaluate (p);
75
76                                 p.Out.WriteFullEndElement ();
77                                 p.PopCDataState (isCData);
78                                 break;
79                         case XPathNodeType.Attribute:
80                                 p.Out.WriteAttributeString (p.CurrentNode.Prefix, p.CurrentNode.LocalName, p.CurrentNode.NamespaceURI, p.CurrentNode.Value);
81                                 break;
82                         
83                         case XPathNodeType.SignificantWhitespace:
84                         case XPathNodeType.Whitespace:
85                                 bool cdata = p.Out.InsideCDataSection;
86                                 p.Out.InsideCDataSection = false;
87                                 p.Out.WriteString (p.CurrentNode.Value);
88                                 p.Out.InsideCDataSection = cdata;
89                                 break;
90                         case XPathNodeType.Text:
91                                 p.Out.WriteString (p.CurrentNode.Value);
92                                 break;
93                         
94                         case XPathNodeType.Comment:
95                                 p.Out.WriteComment (p.CurrentNode.Value);
96                                 break;
97                         
98                         case XPathNodeType.ProcessingInstruction:
99                                 p.Out.WriteProcessingInstruction (p.CurrentNode.Name, p.CurrentNode.Value);
100                                 break;
101
102                         case XPathNodeType.Namespace:
103                                 p.Out.WriteNamespaceDecl (p.CurrentNode.Name, p.CurrentNode.Value);
104                                 break;
105
106                         default:
107 //                              Console.WriteLine ("unhandled node type {0}", p.CurrentNode.NodeType);
108                                 break;
109                         }
110                 }
111         }
112 }