XslTransform.cs 20 KB

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