Parse XSL using PHP

Source: Internet
Author: User
Tags processing instruction xsl
When using PHP to parse XSL in php applications, the template technology is required for data and code separation. Pear, phplib and many companies have provided related templates. However, they share a common drawback: there is no uniform specification, which brings a lot of inconvenience to users. In addition, there are few relevant tutorials and examples, which are too simple to be used for in-depth development and application. XSL is a W3C organization that uses PHP to parse XSL

In php applications, template technology is required for data and code separation. Pear, phplib and many companies have provided related templates. However, they share a common drawback: there is no uniform specification, which brings a lot of inconvenience to users. In addition, there are few relevant tutorials and examples, which are too simple to be used for in-depth development and application.
XSL is a W3C standard and has developed with the application of XML. The tutorials are everywhere and can be used as long as you have IE5. Of course, because it is a new technology, it still lacks support.
Here we will introduce a method to parse XSL using PHP. This method only uses the XML functions provided by PHP, and does not require XSLT that is difficult to configure.
Let's take a look at the example.
Save the following content as resume. xml




Nagging
Xu Zening
Male
1948.10
Anhui province
Czjsz_ah@stats.gov.cn
 
 
C/C ++, VFP, PHP, and JavaScript
 
2001-7-19


Zookeeper
Confidentiality
Male
 
Heilongjiang
Yuepengfei@mail.banner.com.cn
166581208
7665656
 
 
2001-8-15


Sports98
Confidentiality
Male
 
Sichuan
Flyruns@hotmail.com
15787767
11599322
 
Http://www.hiviresearch.com/cgi/report/
2002-1-5



Save the following content as resume1.xsl



Resume






















Moderator information
Alias Name Gender Location Expertise




Save the following content as resume2.xsl



Resume
































Moderator information
Alias Name Gender Location
Time added
Expertise
ICQ
OICQ
Home Page






View resume. xml in ie5 or a later browser and modify the resume. xml file. Resume2.xsl of is resume1.xsl. you can see the page changes. Of course, because not all browsers support this conversion, the conversion must be performed on the server.

Save the following content as xmltest. php
Require_once "pai_class.php ";
$ Xml = new XML;
$ P = new XSL;
$ P-> parser ("resume2.xsl", $ xml-> parser ("resume. xml "));
$ P-> display ();
?>
Transform resume2.xsl, we will still see different pages, just to convert them into HTML format.

Related classes:
Class xml_class parses xml documents to generate a structure similar to domxml
Class performance_class is derived from xml_class and used to parse the xsl document and simulate the xsl function. The template has not yet been implemented.
*****************
Xml_class.php
*****************
Class Element {
Var $ Element; // This node is used for any Element in the document. A subnode of an element node can be an element node of its content, a comment node, an information processing node, and a text node.
Var $ Text; // all texts in the document are grouped into Text nodes. A text node cannot have a sibling node that is followed by a text node.
Var $ Attribute; // Each element node has its own set of Attribute nodes. The default attribute value is processed in the same way as the specified attribute. None of these nodes have subnodes.
Var $ Namespace; // each element that begins with xlmns: and an attribute node has a space name. These nodes do not have subnodes.
Var $ ProcessingInstruction; // Each processing instruction has a separate node. None of these nodes have subnodes.
Var $ Comment; // Each has a Comment node. None of these nodes have subnodes.
Var $ parents = array ();
Var $ childs = array ();
}

Class xml {
Var $ tm = array ();
Var $ xml_parser;
Var $ data = array ();
Var $ element = ""; // current node
Var $ stack = array (); // cache parameters related to the current header
Var $ type;

Function trustedFile ($ file ){
// Only trust local files owned by ourselves
If (! Eregi ("^ ([a-z] +): //", $ file)
& Fileowner ($ file) = getmyuid ()){
Return true;
}
Return false;
}

// Process the start header of an element
Function startElement ($ parser, $ name, $ attribs ){
If ($ this-> element! = ""){
Array_push ($ this-> stack, $ this-> element );
}
$ This-> element = array (Name => $ name );
If (sizeof ($ attribs )){
$ This-> element [Attribute] = $ attribs;
}
}

// Process the end header of an element
Function endElement ($ parser, $ name ){
$ Element = array_pop ($ this-> stack );
If (is_array ($ element )){
$ Element [Element] [] = $ this-> element;
$ This-> element = $ element;
} Else {
$ This-> data [Root] = $ this-> element;
$ This-> element = "";
}
}

// Process the character data header
Function characterData ($ parser, $ data ){
$ Data = eregi_replace ("^ +", "", $ data );
$ Data = eregi_replace ("^ \ n +", "", $ data );
If (strlen ($ data)> 0 ){
$ This-> element [Text]. = $ data;
}
}

// Process the command header
Function PIHandler ($ parser, $ target, $ data ){
Switch (strtolower ($ target )){
Case "php ":
Global $ parser_file;
// If the parsed document is "trusted", we say it is safe
// To execute PHP code inside it. If not, display the code
// Instead.
If ($ this-> trustedFile ($ parser_file [$ parser]) {
Eval ($ data );
} Else {
$ This-> tm [] = sprintf ("Untrusted PHP code: % S",
Htmlspecialchars ($ data ));
}
Break;
Default:
// Echo $ target;
// Echo "=". $ data;
// Echo printf ("% s", $ target, $ data );
Break;
}
}

// Process the specified header
Function defaultHandler ($ parser, $ data ){
If (substr ($ data, 0, 1) = "&" & substr ($ data,-1, 1) = ";"){
$ This-> tm [] = sprintf ('% s ',
Htmlspecialchars ($ data ));
} Else {
$ This-> tm [] = sprintf ('% s ',
Htmlspecialchars ($ data ));
}
}

// Process external entity parameter reference headers
Function externalEntityRefHandler ($ parser, $ openEntityNames, $ base, $ systemId, $ publicId ){
If ($ systemId ){
$ P = new xml;
Return $ p-> parser ($ systemId );
}
Return false;
}

Function parser ($ file ){
Global $ parser_file;

If (! ($ Fp = @ fopen ($ file, "r "))){
Return false;
}
$ This-> xml_parser = xml_parser_create ();
Xml_set_object ($ this-> xml_parser, & $ this); // use the object for the XML parser

Xml_parser_set_option ($ this-> xml_parser, XML_OPTION_CASE_FOLDING, 1 );
Xml_set_element_handler ($ this-> xml_parser, "startElement", "endElement ");
Xml_set_character_data_handler ($ this-> xml_parser, "characterData ");
Xml_set_processing_instruction_handler ($ this-> xml_parser, "PIHandler ");
Xml_set_default_handler ($ this-> xml_parser, "defaultHandler ");
Xml_set_external_entity_ref_handler ($ this-> xml_parser, "externalEntityRefHandler ");

$ This-> type = xml_parser_get_option ($ this-> xml_parser, XML_OPTION_CASE_FOLDING );
While ($ data = fread ($ fp, 4096 )){
If (! Xml_parse ($ this-> xml_parser, $ data, feof ($ fp ))){
Die (sprintf ("XML error: % s at line % d \ n ",
Xml_error_string (xml_get_error_code ($ xml_parser )),
Xml_get_current_line_number ($ xml_parser )));
Return false;
}
}
Xml_parser_free ($ this-> xml_parser );
Return $ this-> data;
}
}
?>

********************
Xsl_class.php
********************

Require_once "xml_class.php ";

Class xsl extends xml {
Var $ datastack = array ();
Var $ sp;
Function parser ($ file, $ dsn = null ){
Parent: parser ($ file );
If ($ dsn! = Null ){
$ This-> dsn [Element] [0] = $ dsn [Root];
}
}
// Process the start header of an element
Function startElement ($ parser, $ name, $ attribs ){
If (eregi ("^ XSL:", $ name )){
$ Ar = split (":", $ name );
Return array_push ($ this-> data, array (xsl => $ ar [1], command => $ attribs ));
}
If (sizeof ($ attribs )){
$ Att = "";
While (list ($ k, $ v) = each ($ attribs )){
$ Att. = "$ k = \" $ v \"";
}
Array_push ($ this-> data, array (tag => "$ name $ att "));
} Else
Array_push ($ this-> data, array (tag => "$ name "));
}

// Process the end header of an element
Function endElement ($ parser, $ name ){
If (! Eregi ("^ XSL:", $ name )){
Array_push ($ this-> data, array (tag => "/$ name "));
} Else {
$ Ar = split (":", $ name );
Array_push ($ this-> data, array (xsl => "/$ ar [1]");
}
}

// Process the character data header
Function characterData ($ parser, $ data ){
$ Data = eregi_replace ("^ [\ n] +", "", $ data );
If (strlen ($ data)> 0 ){
Array_push ($ this-> data, array (text => "$ data "));
}
}

// Process the command header
// Function PIHandler ($ parser, $ target, $ data ){
//}

// Process the specified header
Function defaultHandler ($ parser, $ data ){
}

// Process external entity parameter reference headers
// Function externalEntityRefHandler ($ parser, $ openEntityNames, $ base, $ systemId, $ publicId ){
//}

// XSL instruction parsing
Function compute _parser ($ I ){
For (; $ I Data); $ I ++ ){
$ Key = $ this-> data [$ I];
If (isset ($ key [xsl])
If (eregi ("/xsl", $ key [xsl])
Return $ I;
}
}

// Read data from the data source
Function get_data ($ ps ){
If (! Eregi ("/", $ ps )){
// If it is the default level
$ Ps = join ("/", $ this-> datastack). "/$ ps ";
}
Return "[$ ps]";
}

// Output result
Function display (){
$ This-> stack = array (); // initialize the control stack
$ This-> datastack = array (); // initialize the data stack

$ Type = true; // used to control the output of text items
For ($ id = 0; $ id Data); $ id ++ ){
$ Expr = $ this-> data [$ id];
List ($ key, $ value) = each ($ expr );
Switch ($ key ){
Case "tag ":
Echo "<". $ value. "> ";
If (eregi ("^/", $ value ))
Echo "\ n ";
Break;
Case "text ":
If ($ type)
Echo $ value;
Break;
Case "xsl ":
// Echo $ value;
List (, $ command) = each ($ expr); // retrieves an operation set
$ Value = eregi_replace ("[/-]", "_", strtolower ($ value ));
If (eregi ("eval", $ value ))
$ Value = eregi_replace ("eval", "pai_eval", $ value );
$ This-> $ value ($ command, $ id );
Break;
}
}
}
// Retrieve data, $ dsn start node, $ field node name, $ n matching times
Function find ($ dsn, $ field, $ n = 0 ){
If (! Isset ($ dsn [Element])
Return false;
$ Root = $ dsn [Element];
For ($ I = 0; $ I If ($ this-> type ){
If (eregi ("^". $ field. "$", $ root [$ I] [Name]) {
If (! $ N --)
Return $ root [$ I];
}
} Else {
If (ereg ("^". $ field. "$", $ root [$ I] [Name]) {
If (! $ N --)
Return $ root [$ I];
}
}
}
For ($ I = 0; $ I If ($ ar = $ this-> find ($ root [$ I], $ field, & $ n ))
Return $ ar;
}
Return false;
}

Function for_each ($ command, & $ id ){
// Cyclically press the current id into the stack
Array_push ($ this-> stack, array ($ id, $ command [SELECT], 1 ));
// Retrieve data pointer
$ Data = $ this-> find ($ this-> dsn, $ command [SELECT]);
// Data pointer pushed into stack
Array_push ($ this-> datastack, $ data );
}
Function _ for_each ($ command, & $ id ){
// Obtain the entry address
$ Ar = array_pop ($ this-> stack );
// Discard the current data pointer
Array_pop ($ this-> datastack );
// Check for nesting
If (count ($ this-> datastack)> 0 ){
$ Dsn = array_pop ($ this-> datastack );
Array_push ($ this-> datastack, $ dsn );
} Else
$ Dsn = $ this-> dsn;
$ N = $ ar [2];
// Retrieve data pointer
$ Data = $ this-> find ($ dsn, $ ar [1], $ n );
If ($ data ){
// If retrieved, the loop
$ Ar [2] ++;
Array_push ($ this-> datastack, $ data );
Array_push ($ this-> stack, $ ar );
$ Id = $ ar [0];
}
}
Function value_of ($ command ){
// Obtain the data pointer
If (eregi ("/", $ command [SELECT]) {
} Else {
If (count ($ this-> datastack)> 0 ){
$ Dsn = array_pop ($ this-> datastack );
Array_push ($ this-> datastack, $ dsn );
} Else
$ Dsn = $ this-> dsn;
$ Data = $ this-> find ($ dsn, $ command [SELECT]);
}
Print $ data [Text];
}
Function _ value_of (){
}
Function stylesheet (){
}
Function _ stylesheet (){
}
Function template ($ command ){
Echo join ("", $ command )."
";
}
Function _ template (){
}
Function apply_templates ($ command ){
Echo join ("", $ command )."
";
}
Function _ apply_templates (){
}
Function pai_eval (){
}
Function _ uplo_eval (){
}
}

/***** Appendix ****
Data element node
Array
(
[Name] // Node Name
[Text]
[Attribute]
[Namespace]
[Comment]
[ProcessingInstruction]
[Element] => Array ()
)
*************/
?>

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.