]> granicus.if.org Git - php/commitdiff
Add a readme, this is a substitute to the e-mail I was going to send. it
authorSterling Hughes <sterling@php.net>
Thu, 26 Apr 2001 05:38:17 +0000 (05:38 +0000)
committerSterling Hughes <sterling@php.net>
Thu, 26 Apr 2001 05:38:17 +0000 (05:38 +0000)
gives a basic overview of the new xslt extension and goes into the details
of the api, etc.

ext/xslt/README.XSLT-BACKENDS [new file with mode: 0644]

diff --git a/ext/xslt/README.XSLT-BACKENDS b/ext/xslt/README.XSLT-BACKENDS
new file mode 100644 (file)
index 0000000..7332f4b
--- /dev/null
@@ -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.