1 // System.Xml.Xsl.XslTransform
\r
4 // Tim Coleman <tim@timcoleman.com>
\r
5 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
\r
7 // (C) Copyright 2002 Tim Coleman
\r
8 // (c) 2003 Ximian Inc. (http://www.ximian.com)
\r
12 using System.Collections;
\r
15 using System.Runtime.InteropServices;
\r
16 using System.Xml.XPath;
\r
18 using BF = System.Reflection.BindingFlags;
\r
20 namespace System.Xml.Xsl
\r
22 public unsafe sealed class XslTransform
\r
27 XmlResolver xmlResolver;
\r
29 Hashtable extensionObjectCache = new Hashtable();
\r
33 #region Constructors
\r
34 public XslTransform ()
\r
36 stylesheet = IntPtr.Zero;
\r
43 public XmlResolver XmlResolver {
\r
44 set { xmlResolver = value; }
\r
53 FreeStylesheetIfNeeded ();
\r
56 void FreeStylesheetIfNeeded ()
\r
58 if (stylesheet != IntPtr.Zero) {
\r
59 xsltFreeStylesheet (stylesheet);
\r
60 stylesheet = IntPtr.Zero;
\r
64 // Loads the XSLT stylesheet contained in the IXPathNavigable.
\r
65 public void Load (IXPathNavigable stylesheet)
\r
67 Load (stylesheet.CreateNavigator ());
\r
70 // Loads the XSLT stylesheet specified by a URL.
\r
71 public void Load (string url)
\r
74 throw new ArgumentNullException ("url");
\r
76 FreeStylesheetIfNeeded ();
\r
77 stylesheet = xsltParseStylesheetFile (url);
\r
79 if (stylesheet == IntPtr.Zero)
\r
80 throw new XmlException ("Error creating stylesheet");
\r
83 static IntPtr GetStylesheetFromString (string xml)
\r
85 IntPtr result = IntPtr.Zero;
\r
87 IntPtr xmlDoc = xmlParseDoc (xml);
\r
89 if (xmlDoc == IntPtr.Zero) {
\r
91 throw new XmlException ("Error parsing stylesheet");
\r
94 result = xsltParseStylesheetDoc (xmlDoc);
\r
96 if (result == IntPtr.Zero)
\r
97 throw new XmlException ("Error creating stylesheet");
\r
102 // Loads the XSLT stylesheet contained in the XmlReader
\r
103 public void Load (XmlReader stylesheet)
\r
105 FreeStylesheetIfNeeded ();
\r
106 // Create a document for the stylesheet
\r
107 XmlDocument doc = new XmlDocument ();
\r
108 doc.Load (stylesheet);
\r
110 // Store the XML in a StringBuilder
\r
111 StringWriter sr = new UTF8StringWriter ();
\r
112 XmlTextWriter writer = new XmlTextWriter (sr);
\r
115 this.stylesheet = GetStylesheetFromString (sr.GetStringBuilder ().ToString ());
\r
117 if (this.stylesheet == IntPtr.Zero)
\r
118 throw new XmlException ("Error creating stylesheet");
\r
121 // Loads the XSLT stylesheet contained in the XPathNavigator
\r
122 public void Load (XPathNavigator stylesheet)
\r
124 FreeStylesheetIfNeeded ();
\r
125 StringWriter sr = new UTF8StringWriter ();
\r
126 Save (stylesheet, sr);
\r
127 this.stylesheet = GetStylesheetFromString (sr.GetStringBuilder ().ToString ());
\r
129 if (this.stylesheet == IntPtr.Zero)
\r
130 throw new XmlException ("Error creating stylesheet");
\r
133 [MonoTODO("use the resolver")]
\r
134 // Loads the XSLT stylesheet contained in the IXPathNavigable.
\r
135 public void Load (IXPathNavigable stylesheet, XmlResolver resolver)
\r
140 [MonoTODO("use the resolver")]
\r
141 // Loads the XSLT stylesheet specified by a URL.
\r
142 public void Load (string url, XmlResolver resolver)
\r
147 [MonoTODO("use the resolver")]
\r
148 // Loads the XSLT stylesheet contained in the XmlReader
\r
149 public void Load (XmlReader stylesheet, XmlResolver resolver)
\r
154 [MonoTODO("use the resolver")]
\r
155 // Loads the XSLT stylesheet contained in the XPathNavigator
\r
156 public void Load (XPathNavigator stylesheet, XmlResolver resolver)
\r
161 // Transforms the XML data in the IXPathNavigable using
\r
162 // the specified args and outputs the result to an XmlReader.
\r
163 public XmlReader Transform (IXPathNavigable input, XsltArgumentList args)
\r
166 throw new ArgumentNullException ("input");
\r
168 return Transform (input.CreateNavigator (), args);
\r
171 // Transforms the XML data in the input file and outputs
\r
172 // the result to an output file.
\r
173 public void Transform (string inputfile, string outputfile)
\r
175 IntPtr xmlDocument = IntPtr.Zero;
\r
176 IntPtr resultDocument = IntPtr.Zero;
\r
179 xmlDocument = xmlParseFile (inputfile);
\r
180 if (xmlDocument == IntPtr.Zero)
\r
181 throw new XmlException ("Error parsing input file");
\r
183 resultDocument = ApplyStylesheet (xmlDocument, null, null);
\r
186 * If I do this, the <?xml version=... is always present *
\r
187 if (-1 == xsltSaveResultToFilename (outputfile, resultDocument, stylesheet, 0))
\r
188 throw new XmlException ("Error xsltSaveResultToFilename");
\r
190 StreamWriter writer = new StreamWriter (File.OpenWrite (outputfile));
\r
191 writer.Write (GetStringFromDocument (resultDocument));
\r
194 if (xmlDocument != IntPtr.Zero)
\r
195 xmlFreeDoc (xmlDocument);
\r
197 if (resultDocument != IntPtr.Zero)
\r
198 xmlFreeDoc (resultDocument);
\r
204 IntPtr ApplyStylesheet (IntPtr doc, string[] argArr, Hashtable extobjects)
\r
206 if (stylesheet == IntPtr.Zero)
\r
207 throw new XmlException ("No style sheet!");
\r
211 if (extobjects == null || extobjects.Count == 0) {
\r
212 // If there are no extension objects, use the simple (old) method.
\r
213 result = xsltApplyStylesheet (stylesheet, doc, argArr);
\r
215 // If there are extension objects, create a context and register the functions.
\r
217 IntPtr context = xsltNewTransformContext(stylesheet, doc);
\r
219 if (context == IntPtr.Zero) throw new XmlException("Error creating transformation context.");
\r
222 foreach (string ns in extobjects.Keys) {
\r
223 object ext = extobjects[ns];
\r
225 if (extensionObjectCache.ContainsKey(ext)) {
\r
226 foreach (ExtensionFunctionHolder ef in (ArrayList)extensionObjectCache[ext]) {
\r
227 int ret = xsltRegisterExtFunction(context, ef.name, ef.ns, ef.func);
\r
228 if (ret != 0) throw new XmlException("Could not reregister extension function " + ef.name + " in " + ef.ns);
\r
235 System.Collections.IEnumerable methods;
\r
237 // As an added bonus, if the extension object is a UseStaticMethods object
\r
238 // (defined below), then add the static methods of the specified type.
\r
239 if (ext is UseStaticMethods) {
\r
240 type = ((UseStaticMethods)ext).Type;
\r
241 methods = type.GetMethods(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
\r
245 type = ext.GetType();
\r
246 methods = type.GetMethods();
\r
249 ArrayList functionstocache = new ArrayList();
\r
251 Hashtable alreadyadded = new Hashtable ();
\r
252 foreach (System.Reflection.MethodInfo mi in methods) {
\r
253 if (alreadyadded.ContainsKey(mi.Name)) continue; // don't add twice
\r
254 alreadyadded[mi.Name] = 1;
\r
256 // Simple extension function delegate
\r
257 ExtensionFunction func = new ExtensionFunction(new ReflectedExtensionFunction(type, extsrc, mi.Name).Function);
\r
259 // Delegate for libxslt library call
\r
260 libxsltXPathFunction libfunc = new libxsltXPathFunction(new ExtensionFunctionWrapper(func).Function);
\r
262 int ret = xsltRegisterExtFunction(context, mi.Name, ns, libfunc);
\r
263 if (ret != 0) throw new XmlException("Could not register extension function " + mi.DeclaringType.FullName + "." + mi.Name + " in " + ns);
\r
265 ExtensionFunctionHolder efh;
\r
266 efh.name = mi.Name;
\r
268 efh.func = libfunc;
\r
269 functionstocache.Add(efh);
\r
272 extensionObjectCache[ext] = functionstocache;
\r
278 result = xsltApplyStylesheetUser(stylesheet, doc, argArr, null, IntPtr.Zero, context);
\r
280 xsltFreeTransformContext(context);
\r
285 if (result == IntPtr.Zero)
\r
286 throw new XmlException ("Error applying style sheet");
\r
291 static void Cleanup ()
\r
293 xsltCleanupGlobals ();
\r
294 xmlCleanupParser ();
\r
297 static string GetStringFromDocument (IntPtr doc)
\r
299 IntPtr mem = IntPtr.Zero;
\r
301 xmlDocDumpMemory (doc, ref mem, ref size);
\r
302 if (mem == IntPtr.Zero)
\r
303 throw new XmlException ("Error dumping document");
\r
305 string docStr = Marshal.PtrToStringAnsi (mem, size);
\r
306 // FIXME: Using xmlFree segfaults :-???
\r
308 Marshal.FreeHGlobal (mem);
\r
311 // Get rid of the <?xml...
\r
312 // FIXME: any other (faster) way that works?
\r
313 StringReader result = new StringReader (docStr);
\r
314 result.ReadLine (); // we want the semantics of line ending used here
\r
316 return result.ReadToEnd ();
\r
319 string ApplyStylesheetAndGetString (IntPtr doc, string[] argArr, Hashtable extobjects)
\r
321 IntPtr xmlOutput = ApplyStylesheet (doc, argArr, extobjects);
\r
322 string strOutput = GetStringFromDocument (xmlOutput);
\r
323 xmlFreeDoc (xmlOutput);
\r
328 IntPtr GetDocumentFromNavigator (XPathNavigator nav)
\r
330 StringWriter sr = new UTF8StringWriter ();
\r
332 IntPtr xmlInput = xmlParseDoc (sr.GetStringBuilder ().ToString ());
\r
333 if (xmlInput == IntPtr.Zero)
\r
334 throw new XmlException ("Error getting XML from input");
\r
339 [MonoTODO("Node Set and Node Fragment Parameters and Extension Objects")]
\r
340 // Transforms the XML data in the XPathNavigator using
\r
341 // the specified args and outputs the result to an XmlReader.
\r
342 public XmlReader Transform (XPathNavigator input, XsltArgumentList args)
\r
344 IntPtr xmlInput = GetDocumentFromNavigator (input);
\r
345 string[] argArr = null;
\r
346 Hashtable extensionObjects = null;
\r
347 if (args != null) {
\r
348 extensionObjects = args.extensionObjects;
\r
349 argArr = new string[args.parameters.Count * 2 + 1];
\r
351 foreach (object key in args.parameters.Keys) {
\r
352 argArr [index++] = key.ToString();
\r
353 object value = args.parameters [key];
\r
354 if (value is Boolean)
\r
355 argArr [index++] = XmlConvert.ToString((bool) value); // FIXME: How to encode it for libxslt?
\r
356 else if (value is Double)
\r
357 argArr [index++] = XmlConvert.ToString((double) value); // FIXME: How to encode infinity's and Nan?
\r
359 argArr [index++] = "'" + value.ToString() + "'"; // FIXME: How to encode "'"?
\r
361 argArr[index] = null;
\r
363 string xslOutputString = ApplyStylesheetAndGetString (xmlInput, argArr, extensionObjects);
\r
364 xmlFreeDoc (xmlInput);
\r
367 return new XmlTextReader (new StringReader (xslOutputString));
\r
370 // Transforms the XML data in the IXPathNavigable using
\r
371 // the specified args and outputs the result to a Stream.
\r
372 public void Transform (IXPathNavigable input, XsltArgumentList args, Stream output)
\r
375 throw new ArgumentNullException ("input");
\r
377 Transform (input.CreateNavigator (), args, new StreamWriter (output));
\r
380 // Transforms the XML data in the IXPathNavigable using
\r
381 // the specified args and outputs the result to a TextWriter.
\r
382 public void Transform (IXPathNavigable input, XsltArgumentList args, TextWriter output)
\r
385 throw new ArgumentNullException ("input");
\r
387 Transform (input.CreateNavigator (), args, output);
\r
390 // Transforms the XML data in the IXPathNavigable using
\r
391 // the specified args and outputs the result to an XmlWriter.
\r
392 public void Transform (IXPathNavigable input, XsltArgumentList args, XmlWriter output)
\r
395 throw new ArgumentNullException ("input");
\r
397 Transform (input.CreateNavigator (), args, output);
\r
400 // Transforms the XML data in the XPathNavigator using
\r
401 // the specified args and outputs the result to a Stream.
\r
402 public void Transform (XPathNavigator input, XsltArgumentList args, Stream output)
\r
404 Transform (input, args, new StreamWriter (output));
\r
407 // Transforms the XML data in the XPathNavigator using
\r
408 // the specified args and outputs the result to a TextWriter.
\r
409 [MonoTODO("Node Set and Node Fragment Parameters and Extension Objects")]
\r
410 public void Transform (XPathNavigator input, XsltArgumentList args, TextWriter output)
\r
413 throw new ArgumentNullException ("input");
\r
415 if (output == null)
\r
416 throw new ArgumentNullException ("output");
\r
418 IntPtr inputDoc = GetDocumentFromNavigator (input);
\r
419 string[] argArr = null;
\r
420 Hashtable extensionObjects = null;
\r
421 if (args != null) {
\r
422 extensionObjects = args.extensionObjects;
\r
423 argArr = new string[args.parameters.Count * 2 + 1];
\r
425 foreach (object key in args.parameters.Keys) {
\r
426 argArr [index++] = key.ToString();
\r
427 object value = args.parameters [key];
\r
428 if (value is Boolean)
\r
429 argArr [index++] = XmlConvert.ToString((bool) value); // FIXME: How to encode it for libxslt?
\r
430 else if (value is Double)
\r
431 argArr [index++] = XmlConvert.ToString((double) value); // FIXME: How to encode infinity's and Nan?
\r
433 argArr [index++] = "'" + value.ToString() + "'"; // FIXME: How to encode "'"?
\r
435 argArr[index] = null;
\r
437 string transform = ApplyStylesheetAndGetString (inputDoc, argArr, extensionObjects);
\r
438 xmlFreeDoc (inputDoc);
\r
440 output.Write (transform);
\r
444 // Transforms the XML data in the XPathNavigator using
\r
445 // the specified args and outputs the result to an XmlWriter.
\r
446 public void Transform (XPathNavigator input, XsltArgumentList args, XmlWriter output)
\r
448 StringWriter writer = new UTF8StringWriter ();
\r
449 Transform (input, args, writer);
\r
450 output.WriteRaw (writer.GetStringBuilder ().ToString ());
\r
454 static void Save (XmlReader rdr, TextWriter baseWriter)
\r
456 XmlTextWriter writer = new XmlTextWriter (baseWriter);
\r
458 while (rdr.Read ()) {
\r
459 switch (rdr.NodeType) {
\r
461 case XmlNodeType.CDATA:
\r
462 writer.WriteCData (rdr.Value);
\r
465 case XmlNodeType.Comment:
\r
466 writer.WriteComment (rdr.Value);
\r
469 case XmlNodeType.DocumentType:
\r
470 writer.WriteDocType (rdr.Value, null, null, null);
\r
473 case XmlNodeType.Element:
\r
474 writer.WriteStartElement (rdr.Name, rdr.Value);
\r
476 while (rdr.MoveToNextAttribute ())
\r
477 writer.WriteAttributes (rdr, true);
\r
480 case XmlNodeType.EndElement:
\r
481 writer.WriteEndElement ();
\r
484 case XmlNodeType.ProcessingInstruction:
\r
485 writer.WriteProcessingInstruction (rdr.Name, rdr.Value);
\r
488 case XmlNodeType.Text:
\r
489 writer.WriteString (rdr.Value);
\r
492 case XmlNodeType.Whitespace:
\r
493 writer.WriteWhitespace (rdr.Value);
\r
496 case XmlNodeType.XmlDeclaration:
\r
497 writer.WriteStartDocument ();
\r
505 static void Save (XPathNavigator navigator, TextWriter writer)
\r
507 XmlTextWriter xmlWriter = new XmlTextWriter (writer);
\r
509 WriteTree (navigator, xmlWriter);
\r
510 xmlWriter.WriteEndDocument ();
\r
511 xmlWriter.Flush ();
\r
514 // Walks the XPathNavigator tree recursively
\r
515 static void WriteTree (XPathNavigator navigator, XmlTextWriter writer)
\r
517 WriteCurrentNode (navigator, writer);
\r
519 if (navigator.MoveToFirstAttribute ()) {
\r
521 WriteCurrentNode (navigator, writer);
\r
522 } while (navigator.MoveToNextAttribute ());
\r
524 navigator.MoveToParent ();
\r
527 if (navigator.MoveToFirstChild ()) {
\r
529 WriteTree (navigator, writer);
\r
530 } while (navigator.MoveToNext ());
\r
532 navigator.MoveToParent ();
\r
533 if (navigator.NodeType != XPathNodeType.Root)
\r
534 writer.WriteEndElement ();
\r
535 } else if (navigator.NodeType == XPathNodeType.Element) {
\r
536 writer.WriteEndElement ();
\r
540 // Format the output
\r
541 static void WriteCurrentNode (XPathNavigator navigator, XmlTextWriter writer)
\r
543 switch (navigator.NodeType) {
\r
544 case XPathNodeType.Root:
\r
545 writer.WriteStartDocument ();
\r
547 case XPathNodeType.Attribute:
\r
548 writer.WriteAttributeString (navigator.Name, navigator.Value);
\r
551 case XPathNodeType.Comment:
\r
552 writer.WriteComment (navigator.Value);
\r
555 case XPathNodeType.Element:
\r
556 writer.WriteStartElement (navigator.Name);
\r
559 case XPathNodeType.ProcessingInstruction:
\r
560 writer.WriteProcessingInstruction (navigator.Name, navigator.Value);
\r
563 case XPathNodeType.Text:
\r
564 writer.WriteString (navigator.Value);
\r
567 case XPathNodeType.SignificantWhitespace:
\r
568 case XPathNodeType.Whitespace:
\r
569 writer.WriteWhitespace (navigator.Value);
\r
574 // Extension Objects
\r
576 internal delegate object ExtensionFunction(object[] args);
\r
578 private struct ExtensionFunctionHolder {
\r
579 public libxsltXPathFunction func;
\r
580 public string ns, name;
\r
583 // Wraps an ExtensionFunction into a function that is callable from the libxslt library.
\r
584 private unsafe class ExtensionFunctionWrapper {
\r
585 private readonly ExtensionFunction func;
\r
587 public ExtensionFunctionWrapper(ExtensionFunction func) {
\r
588 if ((object)func == null) throw new ArgumentNullException("func");
\r
592 public unsafe void Function(IntPtr xpath_ctxt, int nargs) {
\r
593 // Convert XPath arguments into "managed" arguments
\r
594 System.Collections.ArrayList args = new System.Collections.ArrayList();
\r
595 for (int i = 0; i < nargs; i++) {
\r
596 xpathobject* aptr = valuePop(xpath_ctxt);
\r
597 if (aptr->type == 2) // Booleans
\r
598 args.Add( xmlXPathCastToBoolean(aptr) == 0 ? false : true );
\r
599 else if (aptr->type == 3) // Doubles
\r
600 args.Add( xmlXPathCastToNumber(aptr));
\r
601 else if (aptr->type == 4) // Strings
\r
602 args.Add( xmlXPathCastToString(aptr));
\r
603 else if (aptr->type == 1 && aptr->nodesetptr != null) { // Node Sets ==> ArrayList of strings
\r
604 System.Collections.ArrayList a = new System.Collections.ArrayList();
\r
605 for (int ni = 0; ni < aptr->nodesetptr->count; ni++) {
\r
606 xpathobject *n = xmlXPathNewNodeSet(aptr->nodesetptr->nodes[ni]);
\r
607 valuePush(xpath_ctxt, n);
\r
608 xmlXPathStringFunction(xpath_ctxt, 1);
\r
609 a.Add(xmlXPathCastToString(valuePop(xpath_ctxt)));
\r
610 xmlXPathFreeObject(n);
\r
613 } else { // Anything else => string
\r
614 valuePush(xpath_ctxt, aptr);
\r
615 xmlXPathStringFunction(xpath_ctxt, 1);
\r
616 args.Add(xmlXPathCastToString(valuePop(xpath_ctxt)));
\r
619 xmlXPathFreeObject(aptr);
\r
624 object ret = func(args.ToArray());
\r
626 // Convert the result back to an XPath object
\r
627 if (ret == null) // null => ""
\r
628 valuePush(xpath_ctxt, xmlXPathNewCString(""));
\r
629 else if (ret is bool) // Booleans
\r
630 valuePush(xpath_ctxt, xmlXPathNewBoolean((bool)ret ? 1 : 0));
\r
631 else if (ret is int || ret is long || ret is double || ret is float || ret is decimal)
\r
633 valuePush(xpath_ctxt, xmlXPathNewFloat((double)ret));
\r
634 else // Everything else => String
\r
635 valuePush(xpath_ctxt, xmlXPathNewCString(ret.ToString()));
\r
640 // Provides a delegate for calling a late-bound method of a type with a given name.
\r
641 // Determines method based on types of arguments.
\r
642 private class ReflectedExtensionFunction {
\r
647 public ReflectedExtensionFunction(System.Type type, object src, string methodname) { this.type = type; this.src = src; this.methodname = methodname; }
\r
649 public object Function(object[] args) {
\r
650 // Construct arg type array, and a stringified version in case of problem
\r
651 System.Type[] argtypes = new System.Type[args.Length];
\r
652 string argtypelist = null;
\r
653 for (int i = 0; i < args.Length; i++) {
\r
654 argtypes[i] = (args[i] == null ? typeof(object) : args[i].GetType() );
\r
656 if (argtypelist != null) argtypelist += ", ";
\r
657 argtypelist += argtypes[i].FullName;
\r
659 if (argtypelist == null) argtypelist = "";
\r
662 System.Reflection.MethodInfo mi = type.GetMethod(methodname, (src == null ? BF.Static : BF.Instance | BF.Static) | BF.Public, null, argtypes, null);
\r
665 if (mi == null) throw new XmlException("No applicable function for " + methodname + " takes (" + argtypelist + ")");
\r
667 if (!mi.IsStatic && src == null) throw new XmlException("Attempt to call static method without instantiated extension object.");
\r
670 return mi.Invoke(src, args);
\r
674 // Special Mono-specific class that allows static methods of a type to
\r
675 // be bound without needing an instance of that type. Useful for
\r
676 // registering System.Math functions, for example.
\r
677 // Usage: args.AddExtensionObject( new XslTransform.UseStaticMethods(typeof(thetype)) );
\r
678 public sealed class UseStaticMethods {
\r
679 public readonly System.Type Type;
\r
680 public UseStaticMethods(System.Type Type) { this.Type = Type; }
\r
685 #region Calls to external libraries
\r
687 [DllImport ("xslt")]
\r
688 static extern IntPtr xsltParseStylesheetFile (string filename);
\r
690 [DllImport ("xslt")]
\r
691 static extern IntPtr xsltParseStylesheetDoc (IntPtr docPtr);
\r
693 [DllImport ("xslt")]
\r
694 static extern IntPtr xsltApplyStylesheet (IntPtr stylePtr, IntPtr DocPtr, string[] argPtr);
\r
696 [DllImport ("xslt")]
\r
697 static extern int xsltSaveResultToFilename (string URI, IntPtr doc, IntPtr styleSheet, int compression);
\r
699 [DllImport ("xslt")]
\r
700 static extern void xsltCleanupGlobals ();
\r
702 [DllImport ("xslt")]
\r
703 static extern void xsltFreeStylesheet (IntPtr cur);
\r
706 [DllImport ("xml2")]
\r
707 static extern IntPtr xmlNewDoc (string version);
\r
709 [DllImport ("xml2")]
\r
710 static extern int xmlSaveFile (string filename, IntPtr cur);
\r
712 [DllImport ("xml2")]
\r
713 static extern IntPtr xmlParseFile (string filename);
\r
715 [DllImport ("xml2")]
\r
716 static extern IntPtr xmlParseDoc (string document);
\r
718 [DllImport ("xml2")]
\r
719 static extern void xmlFreeDoc (IntPtr doc);
\r
721 [DllImport ("xml2")]
\r
722 static extern void xmlCleanupParser ();
\r
724 [DllImport ("xml2")]
\r
725 static extern void xmlDocDumpMemory (IntPtr doc, ref IntPtr mem, ref int size);
\r
727 [DllImport ("xml2")]
\r
728 static extern void xmlFree (IntPtr data);
\r
730 // Functions and structures for extension objects
\r
732 [DllImport ("xslt")]
\r
733 static extern IntPtr xsltNewTransformContext (IntPtr style, IntPtr doc);
\r
735 [DllImport ("xslt")]
\r
736 static extern void xsltFreeTransformContext (IntPtr context);
\r
738 [DllImport ("xslt")]
\r
739 static extern IntPtr xsltApplyStylesheetUser (IntPtr stylePtr, IntPtr DocPtr, string[] argPtr, string output, IntPtr profile, IntPtr context);
\r
741 [DllImport ("xslt")]
\r
742 static extern int xsltRegisterExtFunction (IntPtr context, string name, string uri, libxsltXPathFunction function);
\r
744 [DllImport ("xml2")]
\r
745 unsafe static extern xpathobject* valuePop (IntPtr context);
\r
747 [DllImport ("xml2")]
\r
748 unsafe static extern void valuePush (IntPtr context, xpathobject* data);
\r
750 [DllImport("xml2")]
\r
751 unsafe static extern void xmlXPathFreeObject(xpathobject* obj);
\r
753 [DllImport("xml2")]
\r
754 unsafe static extern xpathobject* xmlXPathNewCString(string str);
\r
756 [DllImport("xml2")]
\r
757 unsafe static extern xpathobject* xmlXPathNewFloat(double val);
\r
759 [DllImport("xml2")]
\r
760 unsafe static extern xpathobject* xmlXPathNewBoolean(int val);
\r
762 [DllImport("xml2")]
\r
763 unsafe static extern xpathobject* xmlXPathNewNodeSet(IntPtr nodeptr);
\r
765 [DllImport("xml2")]
\r
766 unsafe static extern int xmlXPathCastToBoolean(xpathobject* val);
\r
768 [DllImport("xml2")]
\r
769 unsafe static extern double xmlXPathCastToNumber(xpathobject* val);
\r
771 [DllImport("xml2")]
\r
772 unsafe static extern string xmlXPathCastToString(xpathobject* val);
\r
774 [DllImport("xml2")]
\r
775 static extern void xmlXPathStringFunction(IntPtr context, int nargs);
\r
777 private delegate void libxsltXPathFunction(IntPtr xpath_ctxt, int nargs);
\r
779 private struct xpathobject {
\r
781 public xmlnodelist* nodesetptr;
\r
783 private struct xmlnodelist {
\r
785 public int allocated;
\r
786 public IntPtr* nodes;
\r
791 // This classes just makes the base class use 'encoding="utf-8"'
\r
792 class UTF8StringWriter : StringWriter
\r
794 static Encoding encoding = new UTF8Encoding (false);
\r
796 public override Encoding Encoding {
\r