XslTransform.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686
  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,
  178. argArr == null ? new string [0] : argArr,
  179. extobjects == null ? new Hashtable () : extobjects);
  180. string strOutput = GetStringFromDocument (xmlOutput, stylesheet);
  181. xmlFreeDoc (xmlOutput);
  182. return strOutput;
  183. }
  184. IntPtr GetDocumentFromNavigator (XPathNavigator nav)
  185. {
  186. StringWriter sr = new UTF8StringWriter ();
  187. Save (nav, sr);
  188. IntPtr xmlInput = xmlParseDoc (sr.GetStringBuilder ().ToString ());
  189. if (xmlInput == IntPtr.Zero)
  190. throw new XmlException ("Error getting XML from input");
  191. return xmlInput;
  192. }
  193. public override void Transform (XPathNavigator input, XsltArgumentList args, XmlWriter output, XmlResolver resolver)
  194. {
  195. if (input == null)
  196. throw new ArgumentNullException ("input");
  197. if (output == null)
  198. throw new ArgumentNullException ("output");
  199. StringWriter writer = new UTF8StringWriter ();
  200. IntPtr inputDoc = GetDocumentFromNavigator (input);
  201. string[] argArr = null;
  202. Hashtable extensionObjects = null;
  203. if (args != null) {
  204. extensionObjects = args.extensionObjects;
  205. argArr = new string[args.parameters.Count * 2 + 1];
  206. int index = 0;
  207. foreach (object key in args.parameters.Keys) {
  208. argArr [index++] = key.ToString();
  209. object value = args.parameters [key];
  210. if (value is Boolean)
  211. argArr [index++] = XmlConvert.ToString((bool) value); // FIXME: How to encode it for libxslt?
  212. else if (value is Double)
  213. argArr [index++] = XmlConvert.ToString((double) value); // FIXME: How to encode infinity's and Nan?
  214. else
  215. argArr [index++] = "'" + value.ToString() + "'"; // FIXME: How to encode "'"?
  216. }
  217. argArr[index] = null;
  218. }
  219. string transform = ApplyStylesheetAndGetString (inputDoc, argArr, extensionObjects);
  220. xmlFreeDoc (inputDoc);
  221. Cleanup ();
  222. writer.Write (transform);
  223. writer.Flush ();
  224. output.WriteRaw (writer.GetStringBuilder ().ToString ());
  225. output.Flush ();
  226. }
  227. public override void Transform (XPathNavigator input, XsltArgumentList args, TextWriter output, XmlResolver resolver)
  228. {
  229. Transform(input, args, new XmlTextWriter(output), resolver);
  230. }
  231. public override void Transform(string inputfile, string outputfile, XmlResolver resolver)
  232. {
  233. IntPtr xmlDocument = IntPtr.Zero;
  234. IntPtr resultDocument = IntPtr.Zero;
  235. try {
  236. xmlDocument = xmlParseFile (inputfile);
  237. if (xmlDocument == IntPtr.Zero)
  238. throw new XmlException ("Error parsing input file");
  239. resultDocument = ApplyStylesheet (xmlDocument, null, null);
  240. if (-1 == xsltSaveResultToFilename (outputfile, resultDocument, stylesheet, 0))
  241. throw new XmlException ("Error in xsltSaveResultToFilename");
  242. } finally {
  243. if (xmlDocument != IntPtr.Zero)
  244. xmlFreeDoc (xmlDocument);
  245. if (resultDocument != IntPtr.Zero)
  246. xmlFreeDoc (resultDocument);
  247. Cleanup ();
  248. }
  249. }
  250. static void Save (XmlReader rdr, TextWriter baseWriter)
  251. {
  252. XmlTextWriter writer = new XmlTextWriter (baseWriter);
  253. while (rdr.Read ()) {
  254. switch (rdr.NodeType) {
  255. case XmlNodeType.CDATA:
  256. writer.WriteCData (rdr.Value);
  257. break;
  258. case XmlNodeType.Comment:
  259. writer.WriteComment (rdr.Value);
  260. break;
  261. case XmlNodeType.DocumentType:
  262. writer.WriteDocType (rdr.Value, null, null, null);
  263. break;
  264. case XmlNodeType.Element:
  265. writer.WriteStartElement (rdr.Name, rdr.Value);
  266. while (rdr.MoveToNextAttribute ())
  267. writer.WriteAttributes (rdr, true);
  268. break;
  269. case XmlNodeType.EndElement:
  270. writer.WriteEndElement ();
  271. break;
  272. case XmlNodeType.ProcessingInstruction:
  273. writer.WriteProcessingInstruction (rdr.Name, rdr.Value);
  274. break;
  275. case XmlNodeType.Text:
  276. writer.WriteString (rdr.Value);
  277. break;
  278. case XmlNodeType.Whitespace:
  279. writer.WriteWhitespace (rdr.Value);
  280. break;
  281. case XmlNodeType.XmlDeclaration:
  282. writer.WriteStartDocument ();
  283. break;
  284. }
  285. }
  286. writer.Close ();
  287. }
  288. static void Save (XPathNavigator navigator, TextWriter writer)
  289. {
  290. XmlTextWriter xmlWriter = new XmlTextWriter (writer);
  291. WriteTree (navigator, xmlWriter);
  292. xmlWriter.WriteEndDocument ();
  293. xmlWriter.Flush ();
  294. }
  295. // Walks the XPathNavigator tree recursively
  296. static void WriteTree (XPathNavigator navigator, XmlTextWriter writer)
  297. {
  298. WriteCurrentNode (navigator, writer);
  299. if (navigator.MoveToFirstNamespace (XPathNamespaceScope.Local)) {
  300. do {
  301. WriteCurrentNode (navigator, writer);
  302. } while (navigator.MoveToNextNamespace (XPathNamespaceScope.Local));
  303. navigator.MoveToParent ();
  304. }
  305. if (navigator.MoveToFirstAttribute ()) {
  306. do {
  307. WriteCurrentNode (navigator, writer);
  308. } while (navigator.MoveToNextAttribute ());
  309. navigator.MoveToParent ();
  310. }
  311. if (navigator.MoveToFirstChild ()) {
  312. do {
  313. WriteTree (navigator, writer);
  314. } while (navigator.MoveToNext ());
  315. navigator.MoveToParent ();
  316. if (navigator.NodeType != XPathNodeType.Root)
  317. writer.WriteEndElement ();
  318. } else if (navigator.NodeType == XPathNodeType.Element) {
  319. writer.WriteEndElement ();
  320. }
  321. }
  322. // Format the output
  323. static void WriteCurrentNode (XPathNavigator navigator, XmlTextWriter writer)
  324. {
  325. switch (navigator.NodeType) {
  326. case XPathNodeType.Root:
  327. writer.WriteStartDocument ();
  328. break;
  329. case XPathNodeType.Namespace:
  330. if (navigator.Name == String.Empty)
  331. writer.WriteAttributeString ("xmlns", navigator.Value);
  332. else
  333. writer.WriteAttributeString ("xmlns",
  334. navigator.Name,
  335. "http://www.w3.org/2000/xmlns/",
  336. navigator.Value);
  337. break;
  338. case XPathNodeType.Attribute:
  339. writer.WriteAttributeString (navigator.Name, navigator.Value);
  340. break;
  341. case XPathNodeType.Comment:
  342. writer.WriteComment (navigator.Value);
  343. break;
  344. case XPathNodeType.Element:
  345. writer.WriteStartElement (navigator.Name);
  346. break;
  347. case XPathNodeType.ProcessingInstruction:
  348. writer.WriteProcessingInstruction (navigator.Name, navigator.Value);
  349. break;
  350. case XPathNodeType.Text:
  351. writer.WriteString (navigator.Value);
  352. break;
  353. case XPathNodeType.SignificantWhitespace:
  354. case XPathNodeType.Whitespace:
  355. writer.WriteWhitespace (navigator.Value);
  356. break;
  357. }
  358. }
  359. // Extension Objects
  360. internal delegate object ExtensionFunction(object[] args);
  361. private struct ExtensionFunctionHolder {
  362. public libxsltXPathFunction func;
  363. public string ns, name;
  364. }
  365. // Wraps an ExtensionFunction into a function that is callable from the libxslt library.
  366. private unsafe class ExtensionFunctionWrapper {
  367. private readonly ExtensionFunction func;
  368. public ExtensionFunctionWrapper(ExtensionFunction func) {
  369. if ((object)func == null) throw new ArgumentNullException("func");
  370. this.func = func;
  371. }
  372. public unsafe void Function(IntPtr xpath_ctxt, int nargs) {
  373. // Convert XPath arguments into "managed" arguments
  374. System.Collections.ArrayList args = new System.Collections.ArrayList();
  375. for (int i = 0; i < nargs; i++) {
  376. xpathobject* aptr = valuePop(xpath_ctxt);
  377. if (aptr->type == 2) // Booleans
  378. args.Add( xmlXPathCastToBoolean(aptr) == 0 ? false : true );
  379. else if (aptr->type == 3) // Doubles
  380. args.Add( xmlXPathCastToNumber(aptr));
  381. else if (aptr->type == 4) // Strings
  382. args.Add( xmlXPathCastToString(aptr));
  383. else if (aptr->type == 1 && aptr->nodesetptr != null) { // Node Sets ==> ArrayList of strings
  384. System.Collections.ArrayList a = new System.Collections.ArrayList();
  385. for (int ni = 0; ni < aptr->nodesetptr->count; ni++) {
  386. xpathobject *n = xmlXPathNewNodeSet(aptr->nodesetptr->nodes[ni]);
  387. valuePush(xpath_ctxt, n);
  388. xmlXPathStringFunction(xpath_ctxt, 1);
  389. a.Add(xmlXPathCastToString(valuePop(xpath_ctxt)));
  390. xmlXPathFreeObject(n);
  391. }
  392. args.Add(a);
  393. } else { // Anything else => string
  394. valuePush(xpath_ctxt, aptr);
  395. xmlXPathStringFunction(xpath_ctxt, 1);
  396. args.Add(xmlXPathCastToString(valuePop(xpath_ctxt)));
  397. }
  398. xmlXPathFreeObject(aptr);
  399. }
  400. args.Reverse();
  401. object ret = func(args.ToArray());
  402. // Convert the result back to an XPath object
  403. if (ret == null) // null => ""
  404. valuePush(xpath_ctxt, xmlXPathNewCString(""));
  405. else if (ret is bool) // Booleans
  406. valuePush(xpath_ctxt, xmlXPathNewBoolean((bool)ret ? 1 : 0));
  407. else if (ret is int || ret is long || ret is double || ret is float || ret is decimal)
  408. // Numbers
  409. valuePush(xpath_ctxt, xmlXPathNewFloat((double)ret));
  410. else // Everything else => String
  411. valuePush(xpath_ctxt, xmlXPathNewCString(ret.ToString()));
  412. }
  413. }
  414. // Provides a delegate for calling a late-bound method of a type with a given name.
  415. // Determines method based on types of arguments.
  416. private class ReflectedExtensionFunction {
  417. System.Type type;
  418. object src;
  419. string methodname;
  420. public ReflectedExtensionFunction(System.Type type, object src, string methodname) { this.type = type; this.src = src; this.methodname = methodname; }
  421. public object Function(object[] args) {
  422. // Construct arg type array, and a stringified version in case of problem
  423. System.Type[] argtypes = new System.Type[args.Length];
  424. string argtypelist = null;
  425. for (int i = 0; i < args.Length; i++) {
  426. argtypes[i] = (args[i] == null ? typeof(object) : args[i].GetType() );
  427. if (argtypelist != null) argtypelist += ", ";
  428. argtypelist += argtypes[i].FullName;
  429. }
  430. if (argtypelist == null) argtypelist = "";
  431. // Find the method
  432. System.Reflection.MethodInfo mi = type.GetMethod(methodname, (src == null ? BF.Static : BF.Instance | BF.Static) | BF.Public, null, argtypes, null);
  433. // No method?
  434. if (mi == null) throw new XmlException("No applicable function for " + methodname + " takes (" + argtypelist + ")");
  435. if (!mi.IsStatic && src == null) throw new XmlException("Attempt to call static method without instantiated extension object.");
  436. // Invoke
  437. return mi.Invoke(src, args);
  438. }
  439. }
  440. // Special Mono-specific class that allows static methods of a type to
  441. // be bound without needing an instance of that type. Useful for
  442. // registering System.Math functions, for example.
  443. // Usage: args.AddExtensionObject( new XslTransform.UseStaticMethods(typeof(thetype)) );
  444. public sealed class UseStaticMethods {
  445. public readonly System.Type Type;
  446. public UseStaticMethods(System.Type Type) { this.Type = Type; }
  447. }
  448. #endregion
  449. #region Calls to external libraries
  450. // libxslt
  451. [DllImport ("xslt")]
  452. static extern IntPtr xsltParseStylesheetFile (string filename);
  453. [DllImport ("xslt")]
  454. static extern IntPtr xsltParseStylesheetDoc (IntPtr docPtr);
  455. [DllImport ("xslt")]
  456. static extern IntPtr xsltApplyStylesheet (IntPtr stylePtr, IntPtr DocPtr, string[] argPtr);
  457. [DllImport ("xslt")]
  458. static extern int xsltSaveResultToString (ref IntPtr stringPtr, ref int stringLen,
  459. IntPtr docPtr, IntPtr stylePtr);
  460. [DllImport ("xslt")]
  461. static extern int xsltSaveResultToFilename (string URI, IntPtr doc, IntPtr styleSheet, int compression);
  462. [DllImport ("xslt")]
  463. static extern void xsltCleanupGlobals ();
  464. [DllImport ("xslt")]
  465. static extern void xsltFreeStylesheet (IntPtr cur);
  466. // libxml2
  467. [DllImport ("xml2")]
  468. static extern IntPtr xmlNewDoc (string version);
  469. [DllImport ("xml2")]
  470. static extern int xmlSaveFile (string filename, IntPtr cur);
  471. [DllImport ("xml2")]
  472. static extern IntPtr xmlParseFile (string filename);
  473. [DllImport ("xml2")]
  474. static extern IntPtr xmlParseDoc (string document);
  475. [DllImport ("xml2")]
  476. static extern void xmlFreeDoc (IntPtr doc);
  477. [DllImport ("xml2")]
  478. static extern void xmlCleanupParser ();
  479. [DllImport ("xml2")]
  480. static extern void xmlDocDumpMemory (IntPtr doc, ref IntPtr mem, ref int size);
  481. [DllImport ("xml2")]
  482. static extern void xmlFree (IntPtr data);
  483. // Functions and structures for extension objects
  484. [DllImport ("xslt")]
  485. static extern IntPtr xsltNewTransformContext (IntPtr style, IntPtr doc);
  486. [DllImport ("xslt")]
  487. static extern void xsltFreeTransformContext (IntPtr context);
  488. [DllImport ("xslt")]
  489. static extern IntPtr xsltApplyStylesheetUser (IntPtr stylePtr, IntPtr DocPtr, string[] argPtr, string output, IntPtr profile, IntPtr context);
  490. [DllImport ("xslt")]
  491. static extern int xsltRegisterExtFunction (IntPtr context, string name, string uri, libxsltXPathFunction function);
  492. [DllImport ("xml2")]
  493. unsafe static extern xpathobject* valuePop (IntPtr context);
  494. [DllImport ("xml2")]
  495. unsafe static extern void valuePush (IntPtr context, xpathobject* data);
  496. [DllImport("xml2")]
  497. unsafe static extern void xmlXPathFreeObject(xpathobject* obj);
  498. [DllImport("xml2")]
  499. unsafe static extern xpathobject* xmlXPathNewCString(string str);
  500. [DllImport("xml2")]
  501. unsafe static extern xpathobject* xmlXPathNewFloat(double val);
  502. [DllImport("xml2")]
  503. unsafe static extern xpathobject* xmlXPathNewBoolean(int val);
  504. [DllImport("xml2")]
  505. unsafe static extern xpathobject* xmlXPathNewNodeSet(IntPtr nodeptr);
  506. [DllImport("xml2")]
  507. unsafe static extern int xmlXPathCastToBoolean(xpathobject* val);
  508. [DllImport("xml2")]
  509. unsafe static extern double xmlXPathCastToNumber(xpathobject* val);
  510. [DllImport("xml2")]
  511. unsafe static extern string xmlXPathCastToString(xpathobject* val);
  512. [DllImport("xml2")]
  513. static extern void xmlXPathStringFunction(IntPtr context, int nargs);
  514. private delegate void libxsltXPathFunction(IntPtr xpath_ctxt, int nargs);
  515. private struct xpathobject {
  516. public int type;
  517. public xmlnodelist* nodesetptr;
  518. }
  519. private struct xmlnodelist {
  520. public int count;
  521. public int allocated;
  522. public IntPtr* nodes;
  523. }
  524. #endregion
  525. // This classes just makes the base class use 'encoding="utf-8"'
  526. class UTF8StringWriter : StringWriter
  527. {
  528. static Encoding encoding = new UTF8Encoding (false);
  529. public override Encoding Encoding {
  530. get {
  531. return encoding;
  532. }
  533. }
  534. }
  535. }
  536. }