2003-08-21 Gonzalo Paniagua Javier <gonzalo@ximian.com>
[mono.git] / mcs / class / System.XML / System.Xml.Xsl / XslTransform.cs
1 // UnmanagedXslTransform\r
2 //\r
3 // Authors:\r
4 //      Tim Coleman <tim@timcoleman.com>\r
5 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
6 //      Ben Maurer (bmaurer@users.sourceforge.net)\r
7 //\r
8 // (C) Copyright 2002 Tim Coleman\r
9 // (c) 2003 Ximian Inc. (http://www.ximian.com)
10 // (C) Ben Maurer 2003\r
11 //\r
12
13 // DO NOT MOVE THIS FILE. WE WANT HISTORY\r
14 using System;\r
15 using System.Collections;\r
16 using System.IO;\r
17 using System.Security.Policy;\r
18 using System.Text;\r
19 using System.Runtime.InteropServices;\r
20 using System.Xml.XPath;\r
21 \r
22 using BF = System.Reflection.BindingFlags;\r
23 \r
24 namespace System.Xml.Xsl\r
25 {\r
26         internal unsafe sealed class UnmanagedXslTransform : XslTransformImpl\r
27         {\r
28 \r
29                 #region Fields
30                 \r
31                 IntPtr stylesheet;\r
32                 Hashtable extensionObjectCache = new Hashtable();\r
33 \r
34                 #endregion\r
35 \r
36                 #region Constructors\r
37                 public UnmanagedXslTransform ()\r
38                 {\r
39                         stylesheet = IntPtr.Zero;\r
40                 }\r
41 \r
42                 #endregion\r
43 \r
44                 #region Methods\r
45 \r
46                 ~UnmanagedXslTransform ()\r
47                 {\r
48                         FreeStylesheetIfNeeded ();\r
49                 }\r
50 \r
51                 void FreeStylesheetIfNeeded ()\r
52                 {\r
53                         if (stylesheet != IntPtr.Zero) {\r
54                                 xsltFreeStylesheet (stylesheet);\r
55                                 stylesheet = IntPtr.Zero;\r
56                         }\r
57                 }\r
58 \r
59                 public override void Load (string url, XmlResolver resolver)\r
60                 {\r
61                         FreeStylesheetIfNeeded ();\r
62                         stylesheet = xsltParseStylesheetFile (url);\r
63                         Cleanup ();\r
64                         if (stylesheet == IntPtr.Zero)\r
65                                 throw new XmlException ("Error creating stylesheet");\r
66                 }
67                 \r
68                 public override void Load (XmlReader stylesheet, XmlResolver resolver, Evidence evidence)
69                 {
70                         FreeStylesheetIfNeeded ();
71                         // Create a document for the stylesheet
72                         XmlDocument doc = new XmlDocument ();
73                         doc.Load (stylesheet);
74                         
75                         // Store the XML in a StringBuilder
76                         StringWriter sr = new UTF8StringWriter ();
77                         XmlTextWriter writer = new XmlTextWriter (sr);
78                         doc.Save (writer);
79
80                         this.stylesheet = GetStylesheetFromString (sr.GetStringBuilder ().ToString ());
81                         Cleanup ();
82                         if (this.stylesheet == IntPtr.Zero)
83                                 throw new XmlException ("Error creating stylesheet");
84                 }
85
86                 public override void Load (XPathNavigator stylesheet, XmlResolver resolver, Evidence evidence)
87                 {
88                         FreeStylesheetIfNeeded ();
89                         StringWriter sr = new UTF8StringWriter ();
90                         Save (stylesheet, sr);
91                         this.stylesheet = GetStylesheetFromString (sr.GetStringBuilder ().ToString ());
92                         Cleanup ();
93                         if (this.stylesheet == IntPtr.Zero)
94                                 throw new XmlException ("Error creating stylesheet");
95                 }
96                 \r
97                 static IntPtr GetStylesheetFromString (string xml)\r
98                 {\r
99                         IntPtr result = IntPtr.Zero;\r
100 \r
101                         IntPtr xmlDoc = xmlParseDoc (xml);\r
102 \r
103                         if (xmlDoc == IntPtr.Zero) {\r
104                                 Cleanup ();\r
105                                 throw new XmlException ("Error parsing stylesheet");\r
106                         }\r
107                                 \r
108                         result = xsltParseStylesheetDoc (xmlDoc);\r
109                         Cleanup ();\r
110                         if (result == IntPtr.Zero)\r
111                                 throw new XmlException ("Error creating stylesheet");\r
112 \r
113                         return result;\r
114                 }\r
115 \r
116                 IntPtr ApplyStylesheet (IntPtr doc, string[] argArr, Hashtable extobjects)\r
117                 {\r
118                         if (stylesheet == IntPtr.Zero)\r
119                                 throw new XmlException ("No style sheet!");\r
120 \r
121                         IntPtr result;\r
122 \r
123                         if (extobjects == null || extobjects.Count == 0) {\r
124                                 // If there are no extension objects, use the simple (old) method.\r
125                                 result = xsltApplyStylesheet (stylesheet, doc, argArr);\r
126                         } else {\r
127                                 // If there are extension objects, create a context and register the functions.\r
128 \r
129                                 IntPtr context = xsltNewTransformContext(stylesheet, doc);\r
130 \r
131                                 if (context == IntPtr.Zero) throw new XmlException("Error creating transformation context.");\r
132 \r
133                                 try {\r
134                                         foreach (string ns in extobjects.Keys) {\r
135                                                 object ext = extobjects[ns];\r
136 \r
137                                                 if (extensionObjectCache.ContainsKey(ext)) {\r
138                                                         foreach (ExtensionFunctionHolder ef in (ArrayList)extensionObjectCache[ext]) {\r
139                                                                 int ret = xsltRegisterExtFunction(context, ef.name, ef.ns, ef.func);\r
140                                                                 if (ret != 0) throw new XmlException("Could not reregister extension function " + ef.name + " in " + ef.ns);\r
141                                                         }\r
142 \r
143                                                 } else {\r
144                                                         object extsrc;\r
145         \r
146                                                         System.Type type;\r
147                                                         System.Collections.IEnumerable methods;\r
148         \r
149                                                         // As an added bonus, if the extension object is a UseStaticMethods object\r
150                                                         // (defined below), then add the static methods of the specified type.\r
151                                                         if (ext is UseStaticMethods) {\r
152                                                                 type = ((UseStaticMethods)ext).Type;\r
153                                                                 methods = type.GetMethods(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);\r
154                                                                 extsrc = null;\r
155                                                         } else {\r
156                                                                 extsrc = ext;\r
157                                                                 type = ext.GetType();\r
158                                                                 methods = type.GetMethods();\r
159                                                         }\r
160 \r
161                                                         ArrayList functionstocache = new ArrayList();\r
162         \r
163                                                         Hashtable alreadyadded = new Hashtable ();\r
164                                                         foreach (System.Reflection.MethodInfo mi in methods) {\r
165                                                                 if (alreadyadded.ContainsKey(mi.Name)) continue; // don't add twice\r
166                                                                 alreadyadded[mi.Name] = 1;\r
167 \r
168                                                                 // Simple extension function delegate\r
169                                                                 ExtensionFunction func = new ExtensionFunction(new ReflectedExtensionFunction(type, extsrc, mi.Name).Function);\r
170         \r
171                                                                 // Delegate for libxslt library call\r
172                                                                 libxsltXPathFunction libfunc = new libxsltXPathFunction(new ExtensionFunctionWrapper(func).Function);\r
173                 \r
174                                                                 int ret = xsltRegisterExtFunction(context, mi.Name, ns, libfunc);\r
175                                                                 if (ret != 0) throw new XmlException("Could not register extension function " + mi.DeclaringType.FullName + "." + mi.Name + " in " + ns);\r
176 \r
177                                                                 ExtensionFunctionHolder efh;\r
178                                                                 efh.name = mi.Name;\r
179                                                                 efh.ns = ns;\r
180                                                                 efh.func = libfunc;\r
181                                                                 functionstocache.Add(efh);\r
182                                                         }\r
183 \r
184                                                         extensionObjectCache[ext] = functionstocache;\r
185 \r
186                                                 }\r
187                                                 \r
188                                         }\r
189         \r
190                                         result = xsltApplyStylesheetUser(stylesheet, doc, argArr, null, IntPtr.Zero, context);\r
191                                 } finally {\r
192                                         xsltFreeTransformContext(context);\r
193                                 }\r
194                         }\r
195 \r
196 \r
197                         if (result == IntPtr.Zero)\r
198                                 throw new XmlException ("Error applying style sheet");\r
199 \r
200                         return result;\r
201                 }\r
202 \r
203                 static void Cleanup ()\r
204                 {\r
205                         //xsltCleanupGlobals ();\r
206                         //xmlCleanupParser ();\r
207                 }\r
208 \r
209                 static string GetStringFromDocument (IntPtr doc, IntPtr stylesheet)\r
210                 {\r
211                         IntPtr mem = IntPtr.Zero;\r
212                         int size = 0;\r
213 \r
214                         int res = xsltSaveResultToString (ref mem, ref size, doc,\r
215                                                                                           stylesheet);\r
216                         if (res == -1)\r
217                                 throw new XmlException ("xsltSaveResultToString () failed.");\r
218 \r
219                         string docStr = Marshal.PtrToStringAnsi (mem, size);\r
220                         Marshal.FreeHGlobal (mem);\r
221                         return docStr;\r
222                 }\r
223 \r
224                 string ApplyStylesheetAndGetString (IntPtr doc, string[] argArr, Hashtable extobjects)\r
225                 {\r
226                         IntPtr xmlOutput = ApplyStylesheet (doc, argArr, extobjects);\r
227                         string strOutput = GetStringFromDocument (xmlOutput, stylesheet);\r
228                         xmlFreeDoc (xmlOutput);\r
229 \r
230                         return strOutput;\r
231                 }\r
232 \r
233                 IntPtr GetDocumentFromNavigator (XPathNavigator nav)\r
234                 {\r
235                         StringWriter sr = new UTF8StringWriter ();\r
236                         Save (nav, sr);\r
237                         IntPtr xmlInput = xmlParseDoc (sr.GetStringBuilder ().ToString ());\r
238                         if (xmlInput == IntPtr.Zero)\r
239                                 throw new XmlException ("Error getting XML from input");\r
240 \r
241                         return xmlInput;\r
242                 }\r
243 \r
244                 public override void Transform (XPathNavigator input, XsltArgumentList args, XmlWriter output, XmlResolver resolver)
245                 {
246                         if (input == null)
247                                 throw new ArgumentNullException ("input");
248
249                         if (output == null)
250                                 throw new ArgumentNullException ("output");
251
252                         StringWriter writer = new UTF8StringWriter ();
253                         
254                         IntPtr inputDoc = GetDocumentFromNavigator (input);
255                         string[] argArr = null;
256                         Hashtable extensionObjects = null;
257                         if (args != null) {
258                                 extensionObjects = args.extensionObjects;
259                                 argArr = new string[args.parameters.Count * 2 + 1];
260                                 int index = 0;
261                                 foreach (object key in args.parameters.Keys) {
262                                         argArr [index++] = key.ToString();
263                                         object value = args.parameters [key];
264                                         if (value is Boolean)
265                                                 argArr [index++] = XmlConvert.ToString((bool) value); // FIXME: How to encode it for libxslt?
266                                         else if (value is Double)
267                                                 argArr [index++] = XmlConvert.ToString((double) value); // FIXME: How to encode infinity's and Nan?
268                                         else
269                                                 argArr [index++] = "'" + value.ToString() + "'"; // FIXME: How to encode "'"?
270                                 }
271                                 argArr[index] = null;
272                         }
273                         string transform = ApplyStylesheetAndGetString (inputDoc, argArr, extensionObjects);
274                         xmlFreeDoc (inputDoc);
275                         Cleanup ();
276                         writer.Write (transform);
277                         writer.Flush ();
278                         
279                         output.WriteRaw (writer.GetStringBuilder ().ToString ());
280                         output.Flush ();
281                 }
282                 public override void Transform (XPathNavigator input, XsltArgumentList args, TextWriter output, XmlResolver resolver) 
283                 {
284                         Transform(input, args, new XmlTextWriter(output), resolver);
285                 }
286
287                 public override void Transform(string inputfile, string outputfile, XmlResolver resolver)
288                 {
289                         IntPtr xmlDocument = IntPtr.Zero;
290                         IntPtr resultDocument = IntPtr.Zero;
291
292                         try {
293                                 xmlDocument = xmlParseFile (inputfile);
294                                 if (xmlDocument == IntPtr.Zero)
295                                         throw new XmlException ("Error parsing input file");
296
297                                 resultDocument = ApplyStylesheet (xmlDocument, null, null);
298
299                                 if (-1 == xsltSaveResultToFilename (outputfile, resultDocument, stylesheet, 0))
300                                         throw new XmlException ("Error in xsltSaveResultToFilename");
301                         } finally {
302                                 if (xmlDocument != IntPtr.Zero)
303                                         xmlFreeDoc (xmlDocument);
304
305                                 if (resultDocument != IntPtr.Zero)
306                                         xmlFreeDoc (resultDocument);
307
308                                 Cleanup ();
309                         }
310                 }
311 \r
312 \r
313 \r
314                 static void Save (XmlReader rdr, TextWriter baseWriter)\r
315                 {\r
316                         XmlTextWriter writer = new XmlTextWriter (baseWriter);\r
317                 \r
318                         while (rdr.Read ()) {\r
319                                 switch (rdr.NodeType) {\r
320                                 \r
321                                 case XmlNodeType.CDATA:\r
322                                         writer.WriteCData (rdr.Value);\r
323                                         break;\r
324                                 \r
325                                 case XmlNodeType.Comment:\r
326                                         writer.WriteComment (rdr.Value);\r
327                                         break;\r
328 \r
329                                 case XmlNodeType.DocumentType:\r
330                                         writer.WriteDocType (rdr.Value, null, null, null);\r
331                                         break;\r
332 \r
333                                 case XmlNodeType.Element:\r
334                                         writer.WriteStartElement (rdr.Name, rdr.Value);\r
335                                 \r
336                                         while (rdr.MoveToNextAttribute ())\r
337                                                 writer.WriteAttributes (rdr, true);\r
338                                         break;\r
339                         \r
340                                 case XmlNodeType.EndElement:\r
341                                         writer.WriteEndElement ();\r
342                                         break;\r
343 \r
344                                 case XmlNodeType.ProcessingInstruction:\r
345                                         writer.WriteProcessingInstruction (rdr.Name, rdr.Value);\r
346                                         break;\r
347 \r
348                                 case XmlNodeType.Text:\r
349                                         writer.WriteString (rdr.Value);\r
350                                         break;\r
351 \r
352                                 case XmlNodeType.Whitespace:\r
353                                         writer.WriteWhitespace (rdr.Value);\r
354                                         break;\r
355 \r
356                                 case XmlNodeType.XmlDeclaration:\r
357                                         writer.WriteStartDocument ();\r
358                                         break;\r
359                                 }\r
360                         }\r
361 \r
362                         writer.Close ();\r
363                 }\r
364 \r
365                 static void Save (XPathNavigator navigator, TextWriter writer)\r
366                 {\r
367                         XmlTextWriter xmlWriter = new XmlTextWriter (writer);\r
368 \r
369                         WriteTree (navigator, xmlWriter);\r
370                         xmlWriter.WriteEndDocument ();\r
371                         xmlWriter.Flush ();\r
372                 }\r
373 \r
374                 // Walks the XPathNavigator tree recursively \r
375                 static void WriteTree (XPathNavigator navigator, XmlTextWriter writer)\r
376                 {\r
377                         WriteCurrentNode (navigator, writer);\r
378 \r
379                         if (navigator.MoveToFirstNamespace (XPathNamespaceScope.Local)) {\r
380                                 do {\r
381                                         WriteCurrentNode (navigator, writer);\r
382                                 } while (navigator.MoveToNextNamespace (XPathNamespaceScope.Local));\r
383 \r
384                                 navigator.MoveToParent ();\r
385                         }\r
386 \r
387                         if (navigator.MoveToFirstAttribute ()) {\r
388                                 do {\r
389                                         WriteCurrentNode (navigator, writer);\r
390                                 } while (navigator.MoveToNextAttribute ());\r
391 \r
392                                 navigator.MoveToParent ();\r
393                         }\r
394 \r
395                         if (navigator.MoveToFirstChild ()) {\r
396                                 do {\r
397                                         WriteTree (navigator, writer);\r
398                                 } while (navigator.MoveToNext ());\r
399 \r
400                                 navigator.MoveToParent ();\r
401                                 if (navigator.NodeType != XPathNodeType.Root)\r
402                                         writer.WriteEndElement ();\r
403                         } else if (navigator.NodeType == XPathNodeType.Element) {\r
404                                 writer.WriteEndElement ();\r
405                         }\r
406                 }\r
407 \r
408                 // Format the output  \r
409                 static void WriteCurrentNode (XPathNavigator navigator, XmlTextWriter writer)\r
410                 {\r
411                         switch (navigator.NodeType) {\r
412                         case XPathNodeType.Root:\r
413                                 writer.WriteStartDocument ();\r
414                                 break;\r
415                         case XPathNodeType.Namespace:\r
416                                 if (navigator.Name == String.Empty)\r
417                                         writer.WriteAttributeString ("xmlns", navigator.Value);\r
418                                 else\r
419                                         writer.WriteAttributeString ("xmlns",\r
420                                                 navigator.Name,\r
421                                                 "http://www.w3.org/2000/xmlns/",\r
422                                                 navigator.Value);\r
423                                 break;\r
424                         case XPathNodeType.Attribute:\r
425                                 writer.WriteAttributeString (navigator.Name, navigator.Value);\r
426                                 break;\r
427 \r
428                         case XPathNodeType.Comment:\r
429                                 writer.WriteComment (navigator.Value);\r
430                                 break;\r
431 \r
432                         case XPathNodeType.Element:\r
433                                 writer.WriteStartElement (navigator.Name);\r
434                                 break;\r
435                         \r
436                         case XPathNodeType.ProcessingInstruction:\r
437                                 writer.WriteProcessingInstruction (navigator.Name, navigator.Value);\r
438                                 break;\r
439 \r
440                         case XPathNodeType.Text:\r
441                                 writer.WriteString (navigator.Value);\r
442                                 break;\r
443 \r
444                         case XPathNodeType.SignificantWhitespace:\r
445                         case XPathNodeType.Whitespace:\r
446                                 writer.WriteWhitespace (navigator.Value);\r
447                                 break;\r
448                         }\r
449                 }\r
450 \r
451                 // Extension Objects\r
452 \r
453                 internal delegate object ExtensionFunction(object[] args);\r
454 \r
455                 private struct ExtensionFunctionHolder {\r
456                         public libxsltXPathFunction func;\r
457                         public string ns, name;\r
458                 }\r
459 \r
460                 // Wraps an ExtensionFunction into a function that is callable from the libxslt library.\r
461                 private unsafe class ExtensionFunctionWrapper {\r
462                         private readonly ExtensionFunction func;\r
463 \r
464                         public ExtensionFunctionWrapper(ExtensionFunction func) {\r
465                                 if ((object)func == null) throw new ArgumentNullException("func");\r
466                                 this.func = func;\r
467                         }\r
468 \r
469                         public unsafe void Function(IntPtr xpath_ctxt, int nargs) {\r
470                                 // Convert XPath arguments into "managed" arguments\r
471                                 System.Collections.ArrayList args = new System.Collections.ArrayList();\r
472                                 for (int i = 0; i < nargs; i++) {\r
473                                         xpathobject* aptr = valuePop(xpath_ctxt);\r
474                                         if (aptr->type == 2) // Booleans\r
475                                                 args.Add( xmlXPathCastToBoolean(aptr) == 0 ? false : true );\r
476                                         else if (aptr->type == 3) // Doubles\r
477                                                 args.Add( xmlXPathCastToNumber(aptr));\r
478                                         else if (aptr->type == 4) // Strings\r
479                                                 args.Add( xmlXPathCastToString(aptr));\r
480                                         else if (aptr->type == 1 && aptr->nodesetptr != null) { // Node Sets ==> ArrayList of strings\r
481                                                 System.Collections.ArrayList a = new System.Collections.ArrayList();\r
482                                                 for (int ni = 0; ni < aptr->nodesetptr->count; ni++) {\r
483                                                         xpathobject *n = xmlXPathNewNodeSet(aptr->nodesetptr->nodes[ni]);\r
484                                                         valuePush(xpath_ctxt, n);\r
485                                                         xmlXPathStringFunction(xpath_ctxt, 1);\r
486                                                         a.Add(xmlXPathCastToString(valuePop(xpath_ctxt)));\r
487                                                         xmlXPathFreeObject(n);\r
488                                                 }\r
489                                                 args.Add(a);\r
490                                         } else { // Anything else => string\r
491                                                 valuePush(xpath_ctxt, aptr);\r
492                                                 xmlXPathStringFunction(xpath_ctxt, 1);\r
493                                                 args.Add(xmlXPathCastToString(valuePop(xpath_ctxt)));\r
494                                         }\r
495 \r
496                                         xmlXPathFreeObject(aptr);\r
497                                 }\r
498 \r
499                                 args.Reverse();\r
500 \r
501                                 object ret = func(args.ToArray());\r
502 \r
503                                 // Convert the result back to an XPath object\r
504                                 if (ret == null) // null => ""\r
505                                         valuePush(xpath_ctxt, xmlXPathNewCString(""));\r
506                                 else if (ret is bool) // Booleans\r
507                                         valuePush(xpath_ctxt, xmlXPathNewBoolean((bool)ret ? 1 : 0));\r
508                                 else if (ret is int || ret is long || ret is double || ret is float || ret is decimal)\r
509                                         // Numbers\r
510                                         valuePush(xpath_ctxt, xmlXPathNewFloat((double)ret));\r
511                                 else // Everything else => String\r
512                                         valuePush(xpath_ctxt, xmlXPathNewCString(ret.ToString()));\r
513 \r
514                         }\r
515                 }\r
516 \r
517                 // Provides a delegate for calling a late-bound method of a type with a given name.\r
518                 // Determines method based on types of arguments.\r
519                 private class ReflectedExtensionFunction {\r
520                         System.Type type;\r
521                         object src;\r
522                         string methodname;\r
523                 \r
524                         public ReflectedExtensionFunction(System.Type type, object src, string methodname) { this.type = type; this.src = src; this.methodname = methodname; }\r
525                 \r
526                         public object Function(object[] args) {\r
527                                 // Construct arg type array, and a stringified version in case of problem\r
528                                 System.Type[] argtypes = new System.Type[args.Length];\r
529                                 string argtypelist = null;\r
530                                 for (int i = 0; i < args.Length; i++) {\r
531                                         argtypes[i] = (args[i] == null ? typeof(object) : args[i].GetType() );\r
532 \r
533                                         if (argtypelist != null) argtypelist += ", ";\r
534                                         argtypelist += argtypes[i].FullName;\r
535                                 }\r
536                                 if (argtypelist == null) argtypelist = "";\r
537 \r
538                                 // Find the method\r
539                                 System.Reflection.MethodInfo mi = type.GetMethod(methodname, (src == null ? BF.Static : BF.Instance | BF.Static) | BF.Public, null, argtypes, null);\r
540 \r
541                                 // No method?\r
542                                 if (mi == null) throw new XmlException("No applicable function for " + methodname + " takes (" + argtypelist + ")");\r
543 \r
544                                 if (!mi.IsStatic && src == null) throw new XmlException("Attempt to call static method without instantiated extension object.");\r
545 \r
546                                 // Invoke\r
547                                 return mi.Invoke(src, args);\r
548                         }\r
549                 }\r
550 \r
551                 // Special Mono-specific class that allows static methods of a type to\r
552                 // be bound without needing an instance of that type.  Useful for\r
553                 // registering System.Math functions, for example.\r
554                 // Usage:   args.AddExtensionObject( new XslTransform.UseStaticMethods(typeof(thetype)) );\r
555                 public sealed class UseStaticMethods {\r
556                         public readonly System.Type Type;\r
557                         public UseStaticMethods(System.Type Type) { this.Type = Type; }\r
558                 }\r
559 \r
560                 #endregion\r
561 \r
562                 #region Calls to external libraries\r
563                 // libxslt\r
564                 [DllImport ("xslt")]\r
565                 static extern IntPtr xsltParseStylesheetFile (string filename);\r
566 \r
567                 [DllImport ("xslt")]\r
568                 static extern IntPtr xsltParseStylesheetDoc (IntPtr docPtr);\r
569 \r
570                 [DllImport ("xslt")]\r
571                 static extern IntPtr xsltApplyStylesheet (IntPtr stylePtr, IntPtr DocPtr, string[] argPtr);\r
572 \r
573                 [DllImport ("xslt")]\r
574                 static extern int xsltSaveResultToString (ref IntPtr stringPtr, ref int stringLen,\r
575                                                                                                   IntPtr docPtr, IntPtr stylePtr);\r
576 \r
577                 [DllImport ("xslt")]\r
578                 static extern int xsltSaveResultToFilename (string URI, IntPtr doc, IntPtr styleSheet, int compression);\r
579 \r
580                 [DllImport ("xslt")]\r
581                 static extern void xsltCleanupGlobals ();\r
582 \r
583                 [DllImport ("xslt")]\r
584                 static extern void xsltFreeStylesheet (IntPtr cur);\r
585 \r
586                 // libxml2\r
587                 [DllImport ("xml2")]\r
588                 static extern IntPtr xmlNewDoc (string version);\r
589 \r
590                 [DllImport ("xml2")]\r
591                 static extern int xmlSaveFile (string filename, IntPtr cur);\r
592 \r
593                 [DllImport ("xml2")]\r
594                 static extern IntPtr xmlParseFile (string filename);\r
595 \r
596                 [DllImport ("xml2")]\r
597                 static extern IntPtr xmlParseDoc (string document);\r
598 \r
599                 [DllImport ("xml2")]\r
600                 static extern void xmlFreeDoc (IntPtr doc);\r
601 \r
602                 [DllImport ("xml2")]\r
603                 static extern void xmlCleanupParser ();\r
604 \r
605                 [DllImport ("xml2")]\r
606                 static extern void xmlDocDumpMemory (IntPtr doc, ref IntPtr mem, ref int size);\r
607 \r
608                 [DllImport ("xml2")]\r
609                 static extern void xmlFree (IntPtr data);\r
610 \r
611                 // Functions and structures for extension objects\r
612 \r
613                 [DllImport ("xslt")]\r
614                 static extern IntPtr xsltNewTransformContext (IntPtr style, IntPtr doc);\r
615 \r
616                 [DllImport ("xslt")]\r
617                 static extern void xsltFreeTransformContext (IntPtr context);\r
618 \r
619                 [DllImport ("xslt")]\r
620                 static extern IntPtr xsltApplyStylesheetUser (IntPtr stylePtr, IntPtr DocPtr, string[] argPtr, string output, IntPtr profile, IntPtr context);\r
621 \r
622                 [DllImport ("xslt")]\r
623                 static extern int xsltRegisterExtFunction (IntPtr context, string name, string uri, libxsltXPathFunction function);\r
624 \r
625                 [DllImport ("xml2")]\r
626                 unsafe static extern xpathobject* valuePop (IntPtr context);\r
627 \r
628                 [DllImport ("xml2")]\r
629                 unsafe static extern void valuePush (IntPtr context, xpathobject* data);\r
630 \r
631                 [DllImport("xml2")]\r
632                 unsafe static extern void xmlXPathFreeObject(xpathobject* obj);\r
633                 \r
634                 [DllImport("xml2")]\r
635                 unsafe static extern xpathobject* xmlXPathNewCString(string str);\r
636 \r
637                 [DllImport("xml2")]\r
638                 unsafe static extern xpathobject* xmlXPathNewFloat(double val);\r
639 \r
640                 [DllImport("xml2")]\r
641                 unsafe static extern xpathobject* xmlXPathNewBoolean(int val);\r
642 \r
643                 [DllImport("xml2")]\r
644                 unsafe static extern xpathobject* xmlXPathNewNodeSet(IntPtr nodeptr);\r
645 \r
646                 [DllImport("xml2")]\r
647                 unsafe static extern int xmlXPathCastToBoolean(xpathobject* val);\r
648 \r
649                 [DllImport("xml2")]\r
650                 unsafe static extern double xmlXPathCastToNumber(xpathobject* val);\r
651 \r
652                 [DllImport("xml2")]\r
653                 unsafe static extern string xmlXPathCastToString(xpathobject* val);\r
654 \r
655                 [DllImport("xml2")]\r
656                 static extern void xmlXPathStringFunction(IntPtr context, int nargs);\r
657 \r
658                 private delegate void libxsltXPathFunction(IntPtr xpath_ctxt, int nargs);\r
659 \r
660                 private struct xpathobject {\r
661                         public int type;\r
662                         public xmlnodelist* nodesetptr;\r
663                 }\r
664                 private struct xmlnodelist {\r
665                         public int count;\r
666                         public int allocated;\r
667                         public IntPtr* nodes;\r
668                 }\r
669 \r
670                 #endregion\r
671 \r
672                 // This classes just makes the base class use 'encoding="utf-8"'\r
673                 class UTF8StringWriter : StringWriter\r
674                 {\r
675                         static Encoding encoding = new UTF8Encoding (false);\r
676 \r
677                         public override Encoding Encoding {\r
678                                 get {\r
679                                         return encoding;\r
680                                 }\r
681                         }\r
682                 }\r
683         }\r
684 }\r