<?php
/**
 * -----------------------------------------------------------------------------
 *
 * SyL - Web Application Framework for PHP
 *
 * PHP version 4 (>= 4.3.x) or 5
 *
 * Copyright (C) 2006 k.watanabe
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * -----------------------------------------------------------------------------
 * @package   SyL
 * @author    k.watanabe <k.watanabe@syl.jp>
 * @copyright 2006 k.watanabe
 * @license   http://www.opensource.org/licenses/lgpl-license.php
 * @version   CVS: $Id: SyL_XMLParserOperation.php,v 1.8 2007/01/03 11:17:37 seasonstream Exp $
 * @link      http://www.syl.jp/
 * -----------------------------------------------------------------------------
 */

/**
 * XMLパーサークラス
 */
require_once 'SyL_XMLParser.php';

if (!defined('SYL_SCRIPT_ENCODE')) {
    define('SYL_SCRIPT_ENCODE', 'EUC-JP');
}

/**
 *  XML要素取得クラス
 *
 * @package   SyL
 * @author    k.watanabe <k.watanabe@syl.jp>
 * @copyright 2006 k.watanabe
 * @license   http://www.opensource.org/licenses/lgpl-license.php
 * @version   CVS: $Id: SyL_XMLParserOperation.php,v 1.8 2007/01/03 11:17:37 seasonstream Exp $
 * @link      http://www.syl.jp/
 */
class SyL_XMLParserOperation extends SyL_XMLParser
{
    /**
     * 表示文字コード
     *
     * @access private
     * @var string
     */
    var $script_encde = SYL_SCRIPT_ENCODE;
    /**
     * XMLのタグの階層
     *
     * @access private
     * @var int
     */
    var $depth = 0;
    /**
     * タグ有効カレント階層
     *
     * @access private
     * @var int
     */
    var $depth_row = 0;
    /**
     * 現在XML解析中のパス
     *
     * @access private
     * @var array
     */
    var $current_path = array();
    /**
     * XMLのタグの属性値
     *
     * @access private
     * @var array
     */
    var $attribute = array();
    /**
     * XMLのタグの値
     *
     * @access private
     * @var string
     */
    var $text = '';

    /**
     * コンストラクタ
     *
     * @access public
     * @param string XMLファイル名
     */
    function SyL_XMLParserOperation($file_name)
    {
        // 親クラスのコンストラクタ
        parent::SyL_XMLParser($file_name);
    }

    /**
     * XMLファイルのエンコードをセット
     *
     * @access public
     * @param string エンコード名
     */
    function setXmlEncode($xml_encode)
    {
        $this->xml_encode = $xml_encode;
    }

    /**
     * スクリプトのエンコードをセット
     *
     * @access public
     * @param string エンコード名
     */
    function setScriptEncode($script_encde)
    {
        $this->script_encde = $script_encde;
    }

    /**
     * エレメント開始の実行処理
     *
     * @access public
     * @param resource XMLパーサー
     * @param string エレメント名
     * @param array エレメントの属性配列
     */
    function startElement(&$parser, $name, $attr)
    {
        // 文字コード変換
        $name = mb_convert_encoding( $name, $this->script_encde, $this->xml_encode );
        // 属性値取得
        $attribute = array();
        foreach ($attr as $key => $value) {
            $key   = mb_convert_encoding( $key,   $this->script_encde, $this->xml_encode );
            $value = mb_convert_encoding( $value, $this->script_encde, $this->xml_encode );
            $attribute[$key] = $value;
        }

//echo "PATH - " . $name . " - " . $this->depth . " - " .$this->depth_row . "<br>";

        // 保存パスに1階層追加
        $this->current_path[$this->depth] = $name;
        // 保存属性に1階層追加
        $this->attribute[$this->depth] = $attribute;
        // 1階層追加
        $this->depth++;
    }

    /**
     * エレメント終了の実行処理
     *
     * @access public
     * @param resource XMLパーサー
     * @param string エレメント名
     */
    function endElement(&$parser, $name)
    {
        if ($this->text != '') {
            $this->getElement( $this->getCurrentPath(), $this->attribute[count($this->attribute)-1], $this->text );
        }
        // 今までの階層を全要素取得
        $cnt = count($this->attribute);
        $this->getDepthElements( $cnt );

//echo "EE - " . $this->depth . " - " . $this->depth_row . " - " . $this->getCurrentPath() . "<br>";
        // 1階層削除
        $this->depth--;
        $this->depth_row--;
        // 保存パスに1階層削除
        unset($this->current_path[$this->depth]);
        // 保存属性に1階層削除
        unset($this->attribute[$this->depth]);
        // Textを初期化する
        $this->text = '';
    }

    /**
     * キャラクタエレメントの実行処理
     *
     * @access public
     * @param resource XMLパーサー
     * @param string 文字列
     */
    function characters(&$parser, $text)
    {
        if (trim($text) !== '') {
            // 今までの階層を最下層以外全要素取得
            $cnt = count($this->attribute) -1;
            $this->getDepthElements( $cnt );
            $this->depth_row++;
            // 文字コード変換
            $this->text .= mb_convert_encoding( $text, $this->script_encde, $this->xml_encode );
        }
    }

    /**
     * 要素取得
     *
     * @access abstract
     * @param string 現在XML解析中のパス
     * @param string XMLのタグの属性値
     * @param string XMLのタグの値
     */
    function getElement($current_path, $attribute, $text) {}

    /**
     * 今までの階層を全要素取得
     *
     * @access private
     * @param int 階層数
     */
    function getDepthElements($cnt)
    {
        $tmp_path = '';
        for ($i=0; $i<$cnt; $i++) {
            $tmp_path .= '/' . $this->current_path[$i];
            if ($this->depth_row <= $i) {
                $this->getElement( $tmp_path, $this->attribute[$i], null );
                $this->depth_row++;
            }
        }
    }

    /**
     * 現在XML解析中のパスを取得
     *
     * @access public
     * @return string 現在XML解析中のパス
     */
    function getCurrentPath()
    {
        return '/' . implode('/', $this->current_path);
    }
}


?>
