XslTransform.cs 20 KB

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