用PHP解析XSL_PHP

Jun 01, 2016 pm 12:36 PM
data function if nod menghuraikan

    用PHP解析XSL

    在php的应用当中,为做到数据和代码分离需要使用模板技术。pear、phplib及不少公司都提供了相关的模板。但他们有一个共同的缺点:就是没有统一的规范,给使用者带来很多不便。另外有关的教程和范例较少,也太初浅,不易做深层次的开发应用。
    XSL是W3C组织的规范标准,随着XML的应用而发展起来。其教程随处可见,只要你有ie5就可使用。当然由于是新技术,在支持程度上尚显不足。
    这里给大家介绍一种用用PHP解析XSL的方法。该方法仅使用PHP提供的XML函数,无须难以配置的XSLT。
    先看一下例子。
    将以下内容保存为resume.xml




  唠叨
  徐祖宁
  
  1948.10
  安徽
  czjsz_ah@stats.gov.cn
   
   
  C/C++、VFP、PHP、JavaScript
   
  2001-7-19


  刁馋
  保密
  
   
  黑龙江
  yuepengfei@mail.banner.com.cn
  166581208
  7665656
   
   
  2001-8-15


  sports98
  保密
  
   
  四川
  flyruns@hotmail.com
  15787767
  11599322
   
  http://www.hiviresearch.com/cgi/report/
  2002-1-5



    将以下内容保存为resume1.xsl



个人简历






















版主信息
别名 姓名 性别 所在地 专长




    将以下内容保存为resume2.xsl



个人简历
































版主信息
别名 姓名 性别 所在地
加入时间
专长
ICQ
OICQ
主页






    在ie5以上浏览器上查看resume.xml,并可修改resume.xml中 的resume2.xsl为resume1.xsl,可看到页面的变化。当然由于不是所有的浏览器都支持这个转换,所以需要在服务器上进行转换。

    将以下内容保存为xmltest.php
require_once "xsl_class.php";
$xml = new XML;
$p = new XSL;
$p->parser("resume2.xsl",$xml->parser("resume.xml"));
$p->display();
?>
    变换其中的resume2.xsl,我们仍将看到不同的页面,只是以转变成HTML格式了。

   相关的类:
   类xml_class解析xml文档产生一个类似于domxml的结构
   类xsl_class派生于xml_class,用于解析xsl文档并模拟xsl函数,其中template尚未实现。
*****************
   xml_class.php
*****************
class Element {
  var $Element;  // 这种节点用于文档中的任何元素。元素节点的子节点可以是其内容的元素节点、注释节点、处理信息节点以及文本节点。
  var $Text;  // 文档中出现的所有文本,都分组归入到文本节点中。文本节点不可以有同为文本节点的紧接着的前或后的兄弟节点。
  var $Attribute; // 每一个元素节点都有一套自己附加的属性节点。默认的属性值以与指定属性一样的方法来处理。这些节点都没有子节点。
  var $Namespace; // 对于每一个以xlmns:和属性节点开头的元素,都有一个名称空格节点。这些节点没有子节点。
  var $ProcessingInstruction; // 每一个处理指令都有一个单独的节点。这些节点都没有子节点。
  var $Comment; // 每一个都有一个注释节点。这些节点都没有子节点。
  var $parents = array();  
  var $childs = array();  
}

class xml {
  var $tm = array();
  var $xml_parser;
  var $data = array();
  var $element = ""; // 当前节点
  var $stack = array(); // 缓存当前标头的相关参数
  var $type;

  function trustedFile($file) {
    // only trust local files owned by ourselves
    if (!eregi("^([a-z]+)://", $file)
        && fileowner($file) == getmyuid()) {
            return true;
    }
    return false;
  }

  //处理元素的开始标头
  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;
    }
  }

  //处理元素的结束标头
  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 = "";
    }
  }

  //处理字元资料标头
  function characterData($parser, $data) {
    $data = eregi_replace("^ +","",$data);
    $data = eregi_replace("^\n+","",$data);
    if(strlen($data) > 0) {
      $this->element[Text] .= $data;
    }
  }

  //处理指令标头
  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 %s",$target,$data);
        break;
    }
  }

  //处理内定标头
  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));
    }
  }

  //处理外部实体参引标头
  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);  //使 XML 剖析器用对象

    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];
    }
  }
  //处理元素的开始标头
  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"));
  }

  //处理元素的结束标头
  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]"));
    }
  }

  //处理字元资料标头
  function characterData($parser, $data) {
    $data = eregi_replace("^[ \n]+","",$data);
    if(strlen($data) > 0) {
      array_push($this->data,array(text => "$data"));
    }
  }

  //处理指令标头
//  function PIHandler($parser, $target, $data) {
//  }

  //处理内定标头
  function defaultHandler($parser, $data) {
  }

  //处理外部实体参引标头
//  function externalEntityRefHandler($parser, $openEntityNames, $base, $systemId, $publicId) {
//  }

  // XSL指令解析
  function xsl_parser($i) {
    for(;$idata);$i++) {
      $key = $this->data[$i];
      if(isset($key[xsl]))
        if(eregi("/xsl",$key[xsl]))
          return $i;
    }
  }

  // 从数据源读取数据
  function get_data($ps) {
    if(! eregi("/",$ps)) {
      // 若是默认的层次
      $ps = join("/",$this->datastack)."/$ps";
    }
    return "[$ps]";
  }

  // 输出结果
  function display() {
    $this->stack = array();  //初始化控制栈
    $this->datastack = array();  //初始化数据栈

    $type = true;  //用于控制text项的输出
    for($id=0;$iddata);$id++) {
      $expr = $this->data[$id];
      list($key,$value) = each($expr);
      switch($key) {
        case "tag":
          echo "";
          if(eregi("^/",$value))
            echo "\n";
          break;
        case "text":
          if($type)
            echo $value;
          break;
        case "xsl":
//          echo $value;
          list(,$command) = each($expr); // 取得操作集
          $value = eregi_replace("[/-]","_",strtolower($value));
          if(eregi("eval",$value))
            $value = eregi_replace("eval","xsl_eval",$value);
          $this->$value($command,$id);
          break;
      }
    }
  }
  // 检索数据,$dsn开始的节点,$field节点名,$n匹配次数
  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) {
    // 循环,将当前id压入堆栈
    array_push($this->stack,array($id,$command[SELECT],1));
    // 检索数据指针
    $data = $this->find($this->dsn,$command[SELECT]);
    // 数据指针压入堆栈
    array_push($this->datastack,$data);
  }
  function _for_each($command,&$id) {
    // 取得入口地址
    $ar = array_pop($this->stack);
    // 抛弃当前数据指针
    array_pop($this->datastack);
    // 检查是否为嵌套
    if(count($this->datastack) > 0) {
      $dsn = array_pop($this->datastack);
      array_push($this->datastack,$dsn);
    }else
      $dsn = $this->dsn;
    $n = $ar[2];
    // 检索数据指针
    $data = $this->find($dsn,$ar[1],$n);
    if($data) {
      // 如检索到,则循环
      $ar[2]++;
      array_push($this->datastack,$data);
      array_push($this->stack,$ar);
      $id = $ar[0];
    }
  }
  function value_of($command) {
    // 取得数据指针
    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 xsl_eval() {
  }
  function _xsl_eval() {
  }
}

/**** 附录 ****
数据元素节点
Array
(
  [Name] // 节点名
  [Text]
  [Attribute]
  [Namespace]
  [Comment]
  [ProcessingInstruction]
  [Element] => Array()
)
*************/
?>
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

AI Hentai Generator

AI Hentai Generator

Menjana ai hentai secara percuma.

Artikel Panas

R.E.P.O. Kristal tenaga dijelaskan dan apa yang mereka lakukan (kristal kuning)
4 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Tetapan grafik terbaik
4 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Cara Memperbaiki Audio Jika anda tidak dapat mendengar sesiapa
4 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Arahan sembang dan cara menggunakannya
4 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Menyelam mendalam tentang maksud dan penggunaan kod status HTTP 460 Menyelam mendalam tentang maksud dan penggunaan kod status HTTP 460 Feb 18, 2024 pm 08:29 PM

Analisis mendalam tentang peranan dan senario aplikasi kod status HTTP 460 Kod status HTTP adalah bahagian yang sangat penting dalam pembangunan web dan digunakan untuk menunjukkan status komunikasi antara klien dan pelayan. Antaranya, kod status HTTP 460 ialah kod status yang agak istimewa Artikel ini akan menganalisis secara mendalam peranan dan senario aplikasinya. Definisi kod status HTTP 460 Takrif khusus kod status HTTP 460 ialah "ClientClosedRequest", yang bermaksud bahawa klien menutup permintaan. Kod status ini digunakan terutamanya untuk menunjukkan

Bagaimana untuk menulis jika dalam bahasa c untuk menilai pelbagai syarat Bagaimana untuk menulis jika dalam bahasa c untuk menilai pelbagai syarat Mar 25, 2024 pm 03:24 PM

Dalam bahasa C, pernyataan if biasanya digunakan untuk melaksanakan blok kod tertentu berdasarkan satu syarat. Walau bagaimanapun, pelbagai syarat boleh digabungkan untuk membuat penentuan menggunakan operator logik seperti &&, ||, dan !. Termasuk menggunakan logik DAN (&&) untuk menilai berbilang syarat, menggunakan logik ATAU (||) untuk menilai sekurang-kurangnya satu syarat, menggunakan logik NOT (!) untuk menilai penolakan syarat tunggal, serta bersarang jika pernyataan dan menggunakan kurungan untuk menjelaskan keutamaan.

iBatis dan MyBatis: Analisis Perbandingan dan Kelebihan iBatis dan MyBatis: Analisis Perbandingan dan Kelebihan Feb 18, 2024 pm 01:53 PM

iBatis dan MyBatis: Analisis Perbezaan dan Kelebihan Pengenalan: Dalam pembangunan Java, ketekunan adalah keperluan biasa, dan iBatis dan MyBatis ialah dua rangka kerja kegigihan yang digunakan secara meluas. Walaupun mereka mempunyai banyak persamaan, terdapat juga beberapa perbezaan dan kelebihan utama. Artikel ini akan memberikan pembaca pemahaman yang lebih komprehensif melalui analisis terperinci tentang ciri, penggunaan dan kod sampel kedua-dua rangka kerja ini. 1. Ciri iBatis: iBatis ialah rangka kerja kegigihan yang lebih lama yang menggunakan fail pemetaan SQL.

Penjelasan terperinci tentang ralat Oracle 3114: Cara menyelesaikannya dengan cepat Penjelasan terperinci tentang ralat Oracle 3114: Cara menyelesaikannya dengan cepat Mar 08, 2024 pm 02:42 PM

Penjelasan terperinci tentang ralat Oracle 3114: Bagaimana untuk menyelesaikannya dengan cepat, contoh kod khusus diperlukan Semasa pembangunan dan pengurusan pangkalan data Oracle, kami sering menghadapi pelbagai ralat, antaranya ralat 3114 adalah masalah yang agak biasa. Ralat 3114 biasanya menunjukkan masalah dengan sambungan pangkalan data, yang mungkin disebabkan oleh kegagalan rangkaian, pemberhentian perkhidmatan pangkalan data atau tetapan rentetan sambungan yang salah. Artikel ini akan menerangkan secara terperinci punca ralat 3114 dan cara menyelesaikan masalah ini dengan cepat, dan melampirkan kod tertentu

Analisis makna dan penggunaan titik tengah dalam PHP Analisis makna dan penggunaan titik tengah dalam PHP Mar 27, 2024 pm 08:57 PM

[Analisis makna dan penggunaan titik tengah dalam PHP] Dalam PHP, titik tengah (.) ialah operator yang biasa digunakan untuk menyambung dua rentetan atau sifat atau kaedah objek. Dalam artikel ini, kami akan menyelami makna dan penggunaan titik tengah dalam PHP, menggambarkannya dengan contoh kod konkrit. 1. Operator titik tengah rentetan Concatenate Penggunaan yang paling biasa dalam PHP adalah untuk menggabungkan dua rentetan. Dengan meletakkan . antara dua rentetan, anda boleh menyambungkannya untuk membentuk rentetan baharu. $string1=&qu

Parsing Wormhole NTT: rangka kerja terbuka untuk sebarang Token Parsing Wormhole NTT: rangka kerja terbuka untuk sebarang Token Mar 05, 2024 pm 12:46 PM

Wormhole ialah peneraju dalam kebolehkendalian blockchain, memfokuskan pada mencipta sistem terdesentralisasi yang berdaya tahan, kalis masa hadapan yang mengutamakan pemilikan, kawalan dan inovasi tanpa kebenaran. Asas visi ini ialah komitmen terhadap kepakaran teknikal, prinsip etika dan penjajaran komuniti untuk mentakrifkan semula landskap kebolehoperasian dengan kesederhanaan, kejelasan dan rangkaian luas penyelesaian berbilang rantaian. Dengan peningkatan bukti pengetahuan sifar, penyelesaian penskalaan dan piawaian token yang kaya dengan ciri, rantaian blok menjadi lebih berkuasa dan kesalingoperasian menjadi semakin penting. Dalam persekitaran aplikasi yang inovatif ini, sistem tadbir urus baharu dan keupayaan praktikal membawa peluang yang belum pernah berlaku sebelum ini kepada aset merentas rangkaian. Pembina protokol kini bergelut dengan cara untuk beroperasi dalam pelbagai rantaian yang muncul ini

Analisis ciri baharu Win11: Bagaimana untuk melangkau log masuk ke akaun Microsoft Analisis ciri baharu Win11: Bagaimana untuk melangkau log masuk ke akaun Microsoft Mar 27, 2024 pm 05:24 PM

Analisis ciri baharu Win11: Cara melangkau log masuk ke akaun Microsoft Dengan keluaran Windows 11, ramai pengguna mendapati ia membawa lebih banyak kemudahan dan ciri baharu. Walau bagaimanapun, sesetengah pengguna mungkin tidak suka sistem mereka terikat pada akaun Microsoft dan ingin melangkau langkah ini. Artikel ini akan memperkenalkan beberapa kaedah untuk membantu pengguna melangkau log masuk ke akaun Microsoft dalam Windows 11 dan mencapai pengalaman yang lebih peribadi dan autonomi. Mula-mula, mari kita fahami sebab sesetengah pengguna enggan log masuk ke akaun Microsoft mereka. Di satu pihak, sesetengah pengguna bimbang bahawa mereka

Analisis fungsi eksponen dalam bahasa C dan contoh Analisis fungsi eksponen dalam bahasa C dan contoh Feb 18, 2024 pm 03:51 PM

Analisis terperinci dan contoh fungsi eksponen dalam bahasa C Pengenalan: Fungsi eksponen ialah fungsi matematik biasa, dan terdapat fungsi perpustakaan fungsi eksponen sepadan yang boleh digunakan dalam bahasa C. Artikel ini akan menganalisis secara terperinci penggunaan fungsi eksponen dalam bahasa C, termasuk prototaip fungsi, parameter, nilai pulangan, dsb. dan memberikan contoh kod khusus supaya pembaca dapat memahami dan menggunakan fungsi eksponen dengan lebih baik. Teks: Fungsi perpustakaan fungsi eksponen math.h dalam bahasa C mengandungi banyak fungsi yang berkaitan dengan eksponen, yang paling biasa digunakan ialah fungsi exp. Prototaip fungsi exp adalah seperti berikut

See all articles