diff options
-rw-r--r-- | ext/xslt/README.XSLT-BACKENDS | 281 |
1 files changed, 281 insertions, 0 deletions
diff --git a/ext/xslt/README.XSLT-BACKENDS b/ext/xslt/README.XSLT-BACKENDS new file mode 100644 index 0000000000..7332f4be67 --- /dev/null +++ b/ext/xslt/README.XSLT-BACKENDS @@ -0,0 +1,281 @@ ++------------------------------------------------------------------------------+ +| CREATING XSLT BACKENDS | ++------------------------------------------------------------------------------+ + + Author(s): Sterling Hughes <sterling@php.net> + + Introduction + ------------------------------------------------------------------------------- + Truth be told, at this point in time there are about a zillion and two + different XSLT libraries, each with there unique merits and faults. If you + provide a Sablotron extension, people will clamor for a Xalan extension, if you + provide a Xalan extension people will clamor for a libxslt extension. + + In order to be as user friendly as possible, we try and provide the most + amount of options to the user. At the same time we must try to keep a level of + consistency, so the user does not need to remember 15 different syntaxes, etc. + for each XSLT extension, and when switching from XSLT backends, no changes in + the PHP code should be necessary (akin to the concept of a database independent + api, but with XSLT libraries). + + At the same time, you'll also notice that in some cases extensions seem to + duplicate each others functionality. All extensions need code for calling + user-defined handlers, omitting debug messages, etc. In the interests of + laziness, we must also try to make these as minimal as possible. + + Therefore, I've create a processor independent api for XSLT, aka, the XSLT + extension (but doesn't "A processor independent API for XSLT" sound cooler?). + It defines a set of functions which every XSLT backend must provide, as well + as a syntax which those functions must adhere to. Furthermore, the underlying + code, provides a "library" if you will, of code that is relevant to all XSLT + extensions. + + The API + ------------------------------------------------------------------------------- + Every extension must define the following functions: + + - xslt_create() + - xslt_set_scheme_handlers() + - xslt_set_sax_handlers() + - xslt_set_error_handler() + - xslt_set_log() + - xslt_process() + - xslt_error() + - xslt_errno() + - xslt_free() + + These functions are common or implementable with every single XSLT library that + I've come across so far (at least every C library) and should there for be + defined by the extension. + + + resource xslt_create(void) + + The XSLT create function allocates a new XSLT processor and returns a resource + pointer to the XSLT processor. It also handles any initialization that the + processor requires. + + + void xslt_set_scheme_handlers(resource processor, array handlers) + + Registers the scheme handlers for the document (aka XPath handlers), given a + XSLT processor resource (allocated by xslt_create()) and an array in the + following format: + + array( + "get_all" => function, + "open" => function, + "get" => function, + "put" => function, + "close" => function + ) + + Where function is either a function name or an array in the following format: + + array(&$obj, "method") + + Note: The given array does not need to contain all of the different scheme + handler elements (although it can), but it only needs to conform to + the "handler" => "function" format described above. + + Each of the individual scheme handler functions called are in the formats + below: + + string get_all(resource processor, string scheme, string rest) + resource open(resource processor, string scheme, string rest) + int get(resource processor, resource fp, string &data) + int put(resource processor, resource fp, string data) + void close(resource processor, resource fp) + + + void xslt_set_sax_handlers(resource processor, array handlers) + + Registers the SAX handlers for the document, given a XSLT processor resource + (allocated by xslt_create()) and an array in the following format: + + array( + "document" => array(document_start_function, + document_end_function), + "element" => array(element_start_function, + element_end_function), + "namespace" => array(namespace_start_function, + namespace_end_function), + "comment" => function, + "pi" => function, + "character" => function + ) + + Where the functions follow the syntax described for the scheme handler + functions. + + Each of the individual SAX handler functions are in the format below: + + void start_doc(resource processor) + void end_doc(resource processor) + void start_element(resource processor, string name, array attributes) + void end_element(resource processor, string name) + void start_namespace(resource processor, string prefix, string uri) + void end_namespace(resource processor, string prefix) + void comment(resource processor, string contents) + void pi(resource processor, string target, string contents) + void characters(resource processor, string contents) + + + void xslt_set_error_handler(resource processor, function error_handler) + + This function sets the user defined error handler to be called when a + processing or any other type of error occurs. It is given a XSLT + processor resource (allocated by xslt_create()) and an error function of + the same syntax described for the scheme handler function. + + The user defined error handler as the following syntax: + + void error(resource processor, int level, int error, array info) + + + void xslt_set_log(resource processor, string logname) + + Sets the XSLT log to record log information (processor messages, not errors). + Its given a XSLT processor (allocated by xslt_create()) and a string containing + the name of the log file. If the string is "php://stderr" then the logging + should go to standard error (stderr). Also the default place to send log + messages is standard error (if no log file is set). + + + mixed xslt_process(resource processor, + string xml, + string xsl[, + string result[, + array arguments[, + array parameters]]]) + + This function performs the magic, it takes the user's data, performs the + transformation and depending on the context either saves the result to a file + or returns the data to the user. + + To understand the way the xslt_process() function works, you must first + understand the concept of "argument buffers". Argument buffers are equivalent + to the concept of symlinks on a Unix system, take the following example: + + <?php + + /** + * $xml contains the contents of an XML file and $xsl contains + * the contents of an XSLT stylesheet + */ + $args = array("/_xml" => $xml, + "/_xsl" => $xsl); + + $xh = xslt_create(); + $data = xslt_process("arg:/_xml", "arg:/_xsl", NULL, $args); + xslt_free($xh); + + print( "The results of the transformation were\n" ); + print( "<br>\n<hr>\n<br>" ); + print( $data ); + print( "<br>\n<hr>\n<br>" ); + ?> + + See what was done? The argument buffer was declared ($args) and the different + arguments were defined. Then when the xslt_process() function was called + instead of giving the XML filename and XSLT filename we instead gave + "arguments", which correspond to the XML and XSLT data in the argument buffers. + + This concept is a bit foreign to some people, however, I find it the best way + to handle processing xsl data. If your still having trouble with this, try + playing around with the sablotron backend a bit, you should be able to catch on + pretty quickly. + + In order to use argument buffers, the XSLT extension provides a couple of easy + to use API functions, you can use them as follows: + + { + zval **arguments_zp; + char **arguments_cp; + xslt_args *arguments; + char *types[] = { "file", "data" }; + + /* Fetch the arguments from the user into a zval ** */ + + /* Translate the zval array into a character array */ + make_xslt_array(&arguments_cp, arguments_zp); + + /* Translate the character array into an xslt_arg * structure */ + arguments = parse_xslt_arguments(arguments_cp); + + /* Print out the resulting xslt_arg * structure */ + php_printf("XML type: %s\n", types[arguments->xml.type]); + php_printf("XML data: %s\n", arguments->xml.ptr); + PUTS("\n"); + php_printf("XSLT type: %s\n", types[arguments->xsl.type]); + php_printf("XSLT data: %s\n", arguments->xsl.ptr); + PUTS("\n"); + php_printf("Result type: %s\n", types[arguments->result.type]); + php_printf("Result data: %s\n", arguments->result.ptr); + PUTS("\n"); + } + + You can also test the "type" field by using the XSLT_IS_FILE and XSLT_IS_DATA + constants. + + Anyway back to the syntax of the xslt_process() function. The first argument + to the xslt_process() function is a resource pointer to the XSLT processor to + be used. The second argument is either an "argument buffer" pointing to the + XML data or the name of a file containing the XML data. The third argument is + either an argument buffer pointing to the XSLT data or a file containing the + XSLT data. The fourth argument is optional, it either contains the name of the + file to place the results of the transformation into, NULL or "arg:/_result", + in the latter 2 cases, the results of the transformation will be returned. The + fifth optional argument is the "argument buffer" itself, it is an associative + PHP array of "argument_name" => "value" pairs, or NULL, if no arguments are to + be passed. The final optional argument is a set of parameters to pass to the + XSLT stylesheet. The parameter argument is an associative array of + "parameter_name" => "value" pairs. + + + string xslt_error(resource processor) + + The xslt_error() function returns the last error that occured, given a XSLT + processor resource (allocated by xslt_create()). + + + int xslt_errno(resource processor) + + The xslt_errno() function returns the last error number that occured given a + XSLT processor resource (allocated by xslt_create()). + + + void xslt_free(resource processor) + + The xslt_free() function free's the given XSLT processor resource (allocated + by xslt_create()). + + + Config.m4 + ------------------------------------------------------------------------------- + + The XSLT extensions "magic" really occurs in the config.m4 file. Here you must + add a couple of things in order for your backend to be enabled. Its a bit too + complex to describe (but easy to implement and understand). Take a look at + config.m4 (which is well commented) to see what is necessary. + + + Makefile.in + ------------------------------------------------------------------------------- + + Simply add the source files for your backend to the LTLIBRARY_SOURCES variable + and you're all set with this file. + + + Conclusion + ------------------------------------------------------------------------------- + + Nobody's perfect, I'm sure I've made some mistakes while thinking this whole + thing through and I would be glad to here from any of you who think I'm a + colossal moron and think you have a better way to do it. Please e-mail at + sterling@php.net, this extension will only get better with feedback. + + With that said, the concepts here may take a little bit of time to sink in, I + know I've written a whole lot. My suggestion to you, if you're planning on + writing an XSLT backend is simply to go off and implement, taking the api + section as a guide and making sure you match that api as closely as possible. |