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.Xml.XPath;
\r
15 using System.Runtime.InteropServices;
\r
17 using BF = System.Reflection.BindingFlags;
\r
19 namespace System.Xml.Xsl
\r
21 public sealed class XslTransform
\r
26 XmlResolver xmlResolver;
\r
31 #region Constructors
\r
32 public XslTransform ()
\r
34 stylesheet = IntPtr.Zero;
\r
41 public XmlResolver XmlResolver {
\r
42 set { xmlResolver = value; }
\r
51 FreeStylesheetIfNeeded ();
\r
54 void FreeStylesheetIfNeeded ()
\r
56 if (stylesheet != IntPtr.Zero) {
\r
57 xsltFreeStylesheet (stylesheet);
\r
58 stylesheet = IntPtr.Zero;
\r
62 // Loads the XSLT stylesheet contained in the IXPathNavigable.
\r
63 public void Load (IXPathNavigable stylesheet)
\r
65 Load (stylesheet.CreateNavigator ());
\r
68 // Loads the XSLT stylesheet specified by a URL.
\r
69 public void Load (string url)
\r
72 throw new ArgumentNullException ("url");
\r
74 FreeStylesheetIfNeeded ();
\r
75 stylesheet = xsltParseStylesheetFile (url);
\r
77 if (stylesheet == IntPtr.Zero)
\r
78 throw new XmlException ("Error creating stylesheet");
\r
81 static IntPtr GetStylesheetFromString (string xml)
\r
83 IntPtr result = IntPtr.Zero;
\r
85 IntPtr xmlDoc = xmlParseDoc (xml);
\r
87 if (xmlDoc == IntPtr.Zero) {
\r
89 throw new XmlException ("Error parsing stylesheet");
\r
92 result = xsltParseStylesheetDoc (xmlDoc);
\r
94 if (result == IntPtr.Zero)
\r
95 throw new XmlException ("Error creating stylesheet");
\r
100 // Loads the XSLT stylesheet contained in the XmlReader
\r
101 public void Load (XmlReader stylesheet)
\r
103 FreeStylesheetIfNeeded ();
\r
104 // Create a document for the stylesheet
\r
105 XmlDocument doc = new XmlDocument ();
\r
106 doc.Load (stylesheet);
\r
108 // Store the XML in a StringBuilder
\r
109 StringWriter sr = new UTF8StringWriter ();
\r
110 XmlTextWriter writer = new XmlTextWriter (sr);
\r
113 this.stylesheet = GetStylesheetFromString (sr.GetStringBuilder ().ToString ());
\r
115 if (this.stylesheet == IntPtr.Zero)
\r
116 throw new XmlException ("Error creating stylesheet");
\r
119 // Loads the XSLT stylesheet contained in the XPathNavigator
\r
120 public void Load (XPathNavigator stylesheet)
\r
122 FreeStylesheetIfNeeded ();
\r
123 StringWriter sr = new UTF8StringWriter ();
\r
124 Save (stylesheet, sr);
\r
125 this.stylesheet = GetStylesheetFromString (sr.GetStringBuilder ().ToString ());
\r
127 if (this.stylesheet == IntPtr.Zero)
\r
128 throw new XmlException ("Error creating stylesheet");
\r
131 [MonoTODO("use the resolver")]
\r
132 // Loads the XSLT stylesheet contained in the IXPathNavigable.
\r
133 public void Load (IXPathNavigable stylesheet, XmlResolver resolver)
\r
138 [MonoTODO("use the resolver")]
\r
139 // Loads the XSLT stylesheet specified by a URL.
\r
140 public void Load (string url, XmlResolver resolver)
\r
145 [MonoTODO("use the resolver")]
\r
146 // Loads the XSLT stylesheet contained in the XmlReader
\r
147 public void Load (XmlReader stylesheet, XmlResolver resolver)
\r
152 [MonoTODO("use the resolver")]
\r
153 // Loads the XSLT stylesheet contained in the XPathNavigator
\r
154 public void Load (XPathNavigator stylesheet, XmlResolver resolver)
\r
159 // Transforms the XML data in the IXPathNavigable using
\r
160 // the specified args and outputs the result to an XmlReader.
\r
161 public XmlReader Transform (IXPathNavigable input, XsltArgumentList args)
\r
164 throw new ArgumentNullException ("input");
\r
166 return Transform (input.CreateNavigator (), args);
\r
169 // Transforms the XML data in the input file and outputs
\r
170 // the result to an output file.
\r
171 public void Transform (string inputfile, string outputfile)
\r
173 IntPtr xmlDocument = IntPtr.Zero;
\r
174 IntPtr resultDocument = IntPtr.Zero;
\r
177 xmlDocument = xmlParseFile (inputfile);
\r
178 if (xmlDocument == IntPtr.Zero)
\r
179 throw new XmlException ("Error parsing input file");
\r
181 resultDocument = ApplyStylesheet (xmlDocument, null, null);
\r
184 * If I do this, the <?xml version=... is always present *
\r
185 if (-1 == xsltSaveResultToFilename (outputfile, resultDocument, stylesheet, 0))
\r
186 throw new XmlException ("Error xsltSaveResultToFilename");
\r
188 StreamWriter writer = new StreamWriter (File.OpenWrite (outputfile));
\r
189 writer.Write (GetStringFromDocument (resultDocument));
\r
192 if (xmlDocument != IntPtr.Zero)
\r
193 xmlFreeDoc (xmlDocument);
\r
195 if (resultDocument != IntPtr.Zero)
\r
196 xmlFreeDoc (resultDocument);
\r
202 IntPtr ApplyStylesheet (IntPtr doc, string[] argArr, System.Collections.Hashtable extobjects)
\r
204 if (stylesheet == IntPtr.Zero)
\r
205 throw new XmlException ("No style sheet!");
\r
209 if (extobjects == null || extobjects.Count == 0) {
\r
210 // If there are no extension objects, use the simple (old) method.
\r
211 result = xsltApplyStylesheet (stylesheet, doc, argArr);
\r
213 // If there are extension objects, create a context and register the functions.
\r
215 IntPtr context = xsltNewTransformContext(stylesheet, doc);
\r
217 if (context == IntPtr.Zero) throw new XmlException("Error creating transformation context.");
\r
220 foreach (string ns in extobjects.Keys) {
\r
221 object ext = extobjects[ns];
\r
224 System.Collections.IEnumerable methods;
\r
226 // As an added bonus, if the extension object is a UseStaticMethods object
\r
227 // (defined below), then add the static methods of the specified type.
\r
228 if (ext is UseStaticMethods) {
\r
229 type = ((UseStaticMethods)ext).Type;
\r
230 methods = type.GetMethods(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
\r
233 type = ext.GetType();
\r
234 methods = type.GetMethods();
\r
237 System.Collections.Hashtable alreadyadded = new System.Collections.Hashtable();
\r
238 foreach (System.Reflection.MethodInfo mi in methods) {
\r
239 if (alreadyadded.ContainsKey(mi.Name)) continue; // don't add twice
\r
240 alreadyadded[mi.Name] = 1;
\r
242 // Simple extension function delegate
\r
243 ExtensionFunction func = new ExtensionFunction(new ReflectedExtensionFunction(type, ext, mi.Name).Function);
\r
245 // Delegate for libxslt library call
\r
246 libxsltXPathFunction libfunc = new libxsltXPathFunction(new ExtensionFunctionWrapper(func).Function);
\r
248 int ret = xsltRegisterExtFunction(context, mi.Name, ns, libfunc);
\r
249 if (ret != 0) throw new XmlException("Could not register extension function " + mi.DeclaringType.FullName + "." + mi.Name + " in " + ns);
\r
254 result = xsltApplyStylesheetUser(stylesheet, doc, argArr, null, IntPtr.Zero, context);
\r
256 xsltFreeTransformContext(context);
\r
261 if (result == IntPtr.Zero)
\r
262 throw new XmlException ("Error applying style sheet");
\r
267 static void Cleanup ()
\r
269 xsltCleanupGlobals ();
\r
270 xmlCleanupParser ();
\r
273 static string GetStringFromDocument (IntPtr doc)
\r
275 IntPtr mem = IntPtr.Zero;
\r
277 xmlDocDumpMemory (doc, ref mem, ref size);
\r
278 if (mem == IntPtr.Zero)
\r
279 throw new XmlException ("Error dumping document");
\r
281 string docStr = Marshal.PtrToStringAnsi (mem, size);
\r
282 // FIXME: Using xmlFree segfaults :-???
\r
284 Marshal.FreeHGlobal (mem);
\r
287 // Get rid of the <?xml...
\r
288 // FIXME: any other (faster) way that works?
\r
289 StringReader result = new StringReader (docStr);
\r
290 result.ReadLine (); // we want the semantics of line ending used here
\r
292 return result.ReadToEnd ();
\r
295 string ApplyStylesheetAndGetString (IntPtr doc, string[] argArr, System.Collections.Hashtable extobjects)
\r
297 IntPtr xmlOutput = ApplyStylesheet (doc, argArr, extobjects);
\r
298 string strOutput = GetStringFromDocument (xmlOutput);
\r
299 xmlFreeDoc (xmlOutput);
\r
304 IntPtr GetDocumentFromNavigator (XPathNavigator nav)
\r
306 StringWriter sr = new UTF8StringWriter ();
\r
308 IntPtr xmlInput = xmlParseDoc (sr.GetStringBuilder ().ToString ());
\r
309 if (xmlInput == IntPtr.Zero)
\r
310 throw new XmlException ("Error getting XML from input");
\r
315 [MonoTODO("Node Set and Node Fragment Parameters and Extension Objects")]
\r
316 // Transforms the XML data in the XPathNavigator using
\r
317 // the specified args and outputs the result to an XmlReader.
\r
318 public XmlReader Transform (XPathNavigator input, XsltArgumentList args)
\r
320 IntPtr xmlInput = GetDocumentFromNavigator (input);
\r
321 string[] argArr = null;
\r
322 if (args != null) {
\r
323 argArr = new string[args.parameters.Count * 2 + 1];
\r
325 foreach (object key in args.parameters.Keys) {
\r
326 argArr [index++] = key.ToString();
\r
327 object value = args.parameters [key];
\r
328 if (value is Boolean)
\r
329 argArr [index++] = XmlConvert.ToString((bool) value); // FIXME: How to encode it for libxslt?
\r
330 else if (value is Double)
\r
331 argArr [index++] = XmlConvert.ToString((double) value); // FIXME: How to encode infinity's and Nan?
\r
333 argArr [index++] = "'" + value.ToString() + "'"; // FIXME: How to encode "'"?
\r
335 argArr[index] = null;
\r
337 string xslOutputString = ApplyStylesheetAndGetString (xmlInput, argArr, args.extensionObjects);
\r
338 xmlFreeDoc (xmlInput);
\r
341 return new XmlTextReader (new StringReader (xslOutputString));
\r
344 // Transforms the XML data in the IXPathNavigable using
\r
345 // the specified args and outputs the result to a Stream.
\r
346 public void Transform (IXPathNavigable input, XsltArgumentList args, Stream output)
\r
349 throw new ArgumentNullException ("input");
\r
351 Transform (input.CreateNavigator (), args, new StreamWriter (output));
\r
354 // Transforms the XML data in the IXPathNavigable using
\r
355 // the specified args and outputs the result to a TextWriter.
\r
356 public void Transform (IXPathNavigable input, XsltArgumentList args, TextWriter output)
\r
359 throw new ArgumentNullException ("input");
\r
361 Transform (input.CreateNavigator (), args, output);
\r
364 // Transforms the XML data in the IXPathNavigable using
\r
365 // the specified args and outputs the result to an XmlWriter.
\r
366 public void Transform (IXPathNavigable input, XsltArgumentList args, XmlWriter output)
\r
369 throw new ArgumentNullException ("input");
\r
371 Transform (input.CreateNavigator (), args, output);
\r
374 // Transforms the XML data in the XPathNavigator using
\r
375 // the specified args and outputs the result to a Stream.
\r
376 public void Transform (XPathNavigator input, XsltArgumentList args, Stream output)
\r
378 Transform (input, args, new StreamWriter (output));
\r
381 // Transforms the XML data in the XPathNavigator using
\r
382 // the specified args and outputs the result to a TextWriter.
\r
383 [MonoTODO("Node Set and Node Fragment Parameters and Extension Objects")]
\r
384 public void Transform (XPathNavigator input, XsltArgumentList args, TextWriter output)
\r
387 throw new ArgumentNullException ("input");
\r
389 if (output == null)
\r
390 throw new ArgumentNullException ("output");
\r
392 IntPtr inputDoc = GetDocumentFromNavigator (input);
\r
393 string[] argArr = null;
\r
394 if (args != null) {
\r
395 argArr = new string[args.parameters.Count * 2 + 1];
\r
397 foreach (object key in args.parameters.Keys) {
\r
398 argArr [index++] = key.ToString();
\r
399 object value = args.parameters [key];
\r
400 if (value is Boolean)
\r
401 argArr [index++] = XmlConvert.ToString((bool) value); // FIXME: How to encode it for libxslt?
\r
402 else if (value is Double)
\r
403 argArr [index++] = XmlConvert.ToString((double) value); // FIXME: How to encode infinity's and Nan?
\r
405 argArr [index++] = "'" + value.ToString() + "'"; // FIXME: How to encode "'"?
\r
407 argArr[index] = null;
\r
409 string transform = ApplyStylesheetAndGetString (inputDoc, argArr, args.extensionObjects);
\r
410 xmlFreeDoc (inputDoc);
\r
412 output.Write (transform);
\r
416 // Transforms the XML data in the XPathNavigator using
\r
417 // the specified args and outputs the result to an XmlWriter.
\r
418 public void Transform (XPathNavigator input, XsltArgumentList args, XmlWriter output)
\r
420 StringWriter writer = new UTF8StringWriter ();
\r
421 Transform (input, args, writer);
\r
422 output.WriteRaw (writer.GetStringBuilder ().ToString ());
\r
426 static void Save (XmlReader rdr, TextWriter baseWriter)
\r
428 XmlTextWriter writer = new XmlTextWriter (baseWriter);
\r
430 while (rdr.Read ()) {
\r
431 switch (rdr.NodeType) {
\r
433 case XmlNodeType.CDATA:
\r
434 writer.WriteCData (rdr.Value);
\r
437 case XmlNodeType.Comment:
\r
438 writer.WriteComment (rdr.Value);
\r
441 case XmlNodeType.DocumentType:
\r
442 writer.WriteDocType (rdr.Value, null, null, null);
\r
445 case XmlNodeType.Element:
\r
446 writer.WriteStartElement (rdr.Name, rdr.Value);
\r
448 while (rdr.MoveToNextAttribute ())
\r
449 writer.WriteAttributes (rdr, true);
\r
452 case XmlNodeType.EndElement:
\r
453 writer.WriteEndElement ();
\r
456 case XmlNodeType.ProcessingInstruction:
\r
457 writer.WriteProcessingInstruction (rdr.Name, rdr.Value);
\r
460 case XmlNodeType.Text:
\r
461 writer.WriteString (rdr.Value);
\r
464 case XmlNodeType.Whitespace:
\r
465 writer.WriteWhitespace (rdr.Value);
\r
468 case XmlNodeType.XmlDeclaration:
\r
469 writer.WriteStartDocument ();
\r
477 static void Save (XPathNavigator navigator, TextWriter writer)
\r
479 XmlTextWriter xmlWriter = new XmlTextWriter (writer);
\r
481 WriteTree (navigator, xmlWriter);
\r
482 xmlWriter.WriteEndDocument ();
\r
483 xmlWriter.Flush ();
\r
486 // Walks the XPathNavigator tree recursively
\r
487 static void WriteTree (XPathNavigator navigator, XmlTextWriter writer)
\r
489 WriteCurrentNode (navigator, writer);
\r
491 if (navigator.MoveToFirstAttribute ()) {
\r
493 WriteCurrentNode (navigator, writer);
\r
494 } while (navigator.MoveToNextAttribute ());
\r
496 navigator.MoveToParent ();
\r
499 if (navigator.MoveToFirstChild ()) {
\r
501 WriteTree (navigator, writer);
\r
502 } while (navigator.MoveToNext ());
\r
504 navigator.MoveToParent ();
\r
505 if (navigator.NodeType != XPathNodeType.Root)
\r
506 writer.WriteEndElement ();
\r
507 } else if (navigator.NodeType == XPathNodeType.Element) {
\r
508 writer.WriteEndElement ();
\r
512 // Format the output
\r
513 static void WriteCurrentNode (XPathNavigator navigator, XmlTextWriter writer)
\r
515 switch (navigator.NodeType) {
\r
516 case XPathNodeType.Root:
\r
517 writer.WriteStartDocument ();
\r
519 case XPathNodeType.Attribute:
\r
520 writer.WriteAttributeString (navigator.Name, navigator.Value);
\r
523 case XPathNodeType.Comment:
\r
524 writer.WriteComment (navigator.Value);
\r
527 case XPathNodeType.Element:
\r
528 writer.WriteStartElement (navigator.Name);
\r
531 case XPathNodeType.ProcessingInstruction:
\r
532 writer.WriteProcessingInstruction (navigator.Name, navigator.Value);
\r
535 case XPathNodeType.Text:
\r
536 writer.WriteString (navigator.Value);
\r
539 case XPathNodeType.SignificantWhitespace:
\r
540 case XPathNodeType.Whitespace:
\r
541 writer.WriteWhitespace (navigator.Value);
\r
546 // Extension Objects
\r
548 internal delegate object ExtensionFunction(object[] args);
\r
550 // Wraps an ExtensionFunction into a function that is callable from the libxslt library.
\r
551 private unsafe class ExtensionFunctionWrapper {
\r
552 ExtensionFunction func;
\r
554 public ExtensionFunctionWrapper(ExtensionFunction func) { this.func = func; }
\r
556 public unsafe void Function(IntPtr xpath_ctxt, int nargs) {
\r
558 // Convert XPath arguments into "managed" arguments
\r
559 System.Collections.ArrayList args = new System.Collections.ArrayList();
\r
560 for (int i = 0; i < nargs; i++) {
\r
561 xpathobject* aptr = valuePop(xpath_ctxt);
\r
562 if (aptr->type == 2) // Booleans
\r
563 args.Add( xmlXPathCastToBoolean(aptr) == 0 ? false : true );
\r
564 else if (aptr->type == 3) // Doubles
\r
565 args.Add( xmlXPathCastToNumber(aptr));
\r
566 else if (aptr->type == 4) // Strings
\r
567 args.Add( xmlXPathCastToString(aptr));
\r
568 else if (aptr->type == 1) { // Node Sets ==> ArrayList of strings
\r
569 System.Collections.ArrayList a = new System.Collections.ArrayList();
\r
570 for (int ni = 0; ni < aptr->nodesetptr->count; ni++) {
\r
571 xpathobject *n = xmlXPathNewNodeSet(aptr->nodesetptr->nodes[ni]);
\r
572 valuePush(xpath_ctxt, n);
\r
573 xmlXPathStringFunction(xpath_ctxt, 1);
\r
574 a.Add(xmlXPathCastToString(valuePop(xpath_ctxt)));
\r
575 xmlXPathFreeObject(n);
\r
578 } else { // Anything else => string
\r
579 valuePush(xpath_ctxt, aptr);
\r
580 xmlXPathStringFunction(xpath_ctxt, 1);
\r
581 args.Add(xmlXPathCastToString(valuePop(xpath_ctxt)));
\r
584 xmlXPathFreeObject(aptr);
\r
589 object ret = func(args.ToArray());
\r
591 // Convert the result back to an XPath object
\r
592 if (ret == null) // null => ""
\r
593 valuePush(xpath_ctxt, xmlXPathNewCString(""));
\r
594 else if (ret is Boolean) // Booleans
\r
595 valuePush(xpath_ctxt, xmlXPathNewBoolean((bool)ret ? 1 : 0));
\r
596 else if (ret is int || ret is long || ret is double || ret is float || ret is decimal)
\r
598 valuePush(xpath_ctxt, xmlXPathNewFloat((double)ret));
\r
600 valuePush(xpath_ctxt, xmlXPathNewCString(ret.ToString()));
\r
605 // Provides a delegate for calling a late-bound method of a type with a given name.
\r
606 // Determines method based on types of arguments.
\r
607 private class ReflectedExtensionFunction {
\r
612 public ReflectedExtensionFunction(System.Type type, object src, string methodname) { this.type = type; this.src = src; this.methodname = methodname; }
\r
614 public object Function(object[] args) {
\r
615 // Construct arg type array, stringified version in case of problem
\r
616 System.Type[] argtypes = new System.Type[args.Length];
\r
617 string argtypelist = null;
\r
618 for (int i = 0; i < args.Length; i++) {
\r
619 argtypes[i] = (args[i] == null ? typeof(object) : args[i].GetType() );
\r
621 if (argtypelist != null) argtypelist += ", ";
\r
622 argtypelist += argtypes[i].FullName;
\r
624 if (argtypelist == null) argtypelist = "";
\r
627 System.Reflection.MethodInfo mi = type.GetMethod(methodname, (src == null ? BF.Static : BF.Instance | BF.Static) | BF.Public, null, argtypes, null);
\r
630 if (mi == null) throw new XmlException("No applicable function for " + methodname + " takes (" + argtypelist + ")");
\r
633 return mi.Invoke(src, args);
\r
637 // Special Mono-specific class that allows static methods of a type to
\r
638 // be bound without needing an instance of that type. Useful for
\r
639 // registering System.Math functions, for example.
\r
640 // Usage: args.AddExtensionObject( new XslTransform.UseStaticMethods(typeof(thetype)) );
\r
641 public sealed class UseStaticMethods {
\r
642 public readonly System.Type Type;
\r
643 public UseStaticMethods(System.Type Type) { this.Type = Type; }
\r
648 #region Calls to external libraries
\r
650 [DllImport ("xslt")]
\r
651 static extern IntPtr xsltParseStylesheetFile (string filename);
\r
653 [DllImport ("xslt")]
\r
654 static extern IntPtr xsltParseStylesheetDoc (IntPtr docPtr);
\r
656 [DllImport ("xslt")]
\r
657 static extern IntPtr xsltApplyStylesheet (IntPtr stylePtr, IntPtr DocPtr, string[] argPtr);
\r
659 [DllImport ("xslt")]
\r
660 static extern int xsltSaveResultToFilename (string URI, IntPtr doc, IntPtr styleSheet, int compression);
\r
662 [DllImport ("xslt")]
\r
663 static extern void xsltCleanupGlobals ();
\r
665 [DllImport ("xslt")]
\r
666 static extern void xsltFreeStylesheet (IntPtr cur);
\r
669 [DllImport ("xml2")]
\r
670 static extern IntPtr xmlNewDoc (string version);
\r
672 [DllImport ("xml2")]
\r
673 static extern int xmlSaveFile (string filename, IntPtr cur);
\r
675 [DllImport ("xml2")]
\r
676 static extern IntPtr xmlParseFile (string filename);
\r
678 [DllImport ("xml2")]
\r
679 static extern IntPtr xmlParseDoc (string document);
\r
681 [DllImport ("xml2")]
\r
682 static extern void xmlFreeDoc (IntPtr doc);
\r
684 [DllImport ("xml2")]
\r
685 static extern void xmlCleanupParser ();
\r
687 [DllImport ("xml2")]
\r
688 static extern void xmlDocDumpMemory (IntPtr doc, ref IntPtr mem, ref int size);
\r
690 [DllImport ("xml2")]
\r
691 static extern void xmlFree (IntPtr data);
\r
693 // Functions and structures for extension objects
\r
695 [DllImport ("xslt")]
\r
696 static extern IntPtr xsltNewTransformContext (IntPtr style, IntPtr doc);
\r
698 [DllImport ("xslt")]
\r
699 static extern void xsltFreeTransformContext (IntPtr context);
\r
701 [DllImport ("xslt")]
\r
702 static extern IntPtr xsltApplyStylesheetUser (IntPtr stylePtr, IntPtr DocPtr, string[] argPtr, string output, IntPtr profile, IntPtr context);
\r
704 [DllImport ("xslt")]
\r
705 static extern int xsltRegisterExtFunction (IntPtr context, string name, string uri, libxsltXPathFunction function);
\r
707 [DllImport ("xml2")]
\r
708 unsafe static extern xpathobject* valuePop (IntPtr context);
\r
710 [DllImport ("xml2")]
\r
711 unsafe static extern void valuePush (IntPtr context, xpathobject* data);
\r
713 [DllImport("xml2")]
\r
714 unsafe static extern void xmlXPathFreeObject(xpathobject* obj);
\r
716 [DllImport("xml2")]
\r
717 unsafe static extern xpathobject* xmlXPathNewCString(string str);
\r
719 [DllImport("xml2")]
\r
720 unsafe static extern xpathobject* xmlXPathNewFloat(double val);
\r
722 [DllImport("xml2")]
\r
723 unsafe static extern xpathobject* xmlXPathNewBoolean(int val);
\r
725 [DllImport("xml2")]
\r
726 unsafe static extern xpathobject* xmlXPathNewNodeSet(IntPtr nodeptr);
\r
728 [DllImport("xml2")]
\r
729 unsafe static extern int xmlXPathCastToBoolean(xpathobject* val);
\r
731 [DllImport("xml2")]
\r
732 unsafe static extern double xmlXPathCastToNumber(xpathobject* val);
\r
734 [DllImport("xml2")]
\r
735 unsafe static extern string xmlXPathCastToString(xpathobject* val);
\r
737 [DllImport("xml2")]
\r
738 static extern void xmlXPathStringFunction(IntPtr context, int nargs);
\r
740 private delegate void libxsltXPathFunction(IntPtr xpath_ctxt, int nargs);
\r
742 private struct xpathobject {
\r
744 public xmlnodelist* nodesetptr;
\r
746 private struct xmlnodelist {
\r
748 public int allocated;
\r
749 public IntPtr* nodes;
\r
754 // This classes just makes the base class use 'encoding="utf-8"'
\r
755 class UTF8StringWriter : StringWriter
\r
757 static Encoding encoding = new UTF8Encoding (false);
\r
759 public override Encoding Encoding {
\r