Поиск:

Ответ в темуСоздание новой темы Создание опроса
> XmlI класс для работы с XML. давайте обсудим достатки и недостатки 
V
    Опции темы
IZ@TOP
Дата 30.8.2005, 21:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Панда-бир!
****


Профиль
Группа: Участник
Сообщений: 4795
Регистрация: 3.2.2003
Где: Бамбуковый лес

Репутация: нет
Всего: 73



В общем имеется класс для работы с XML (думаю что его можно переписать под 5 РНР).
Давайте обсудим все достатки и недостатки моего подхода к этому вопросу.

Код

define('XMLI_LOAD_FILE',        1);
define('XMLI_LOAD_TEXT',        2);
define('XMLI_NEW_DOCUMENT',        3);

define('XMLI_ASSOC_KEYS',        1);
define('XMLI_NUMBER_KEYS',        2);

define('XMLI_SAVE_PATH',        FRAMEWROK_EXT_PATH.'/Temp-Cache/Web.Xml');

define('XMLI_XINCLUDE_NS',        'http://www.w3.org/2001/XInclude');
define('XMLI_XINCLUDE_PREFIX',    'xi');


class XmlI {
    
    /**
     * Объект DomDocument
     *
     * @var DomDocument
     */
    var $XmlHandler                = null;
    
    /**
     * Элемент верхнего уровня XML дерева.
     *
     * @var DomNode
     */
    var $rootNode                = null;
    
    /**
     * Содержит путь для сохранения XML Документов.
     *
     * @var string
     */
    var $SavePath                = XMLI_SAVE_PATH;
    
    /**
     * Последняя строка XPath запроса
     *
     * @var string
     */
    var $xPath                    = null;
    
    /**
     * Массив содержащий в себе ноды найденные после выполнения XPath запроса.
     *
     * @var array
     */
    var $resultNodes            = array();
    
    
    /**
     * Функция конструктор класса.
     * Принимает аргументы для создания, загрузки XML документа.
     * @param    $in        string
     * @param    $action    int
     * @return    this
     */
    function XmlI($in = '', $action = 0) {

        switch($action) {
        
            case XMLI_LOAD_FILE: {
                
                $this->load($in, $action);
                break;
                
            }
            
            case XMLI_LOAD_TEXT: {
            
                $this->load($in, $action);
                break;
                    
            }
            
            case XMLI_NEW_DOCUMENT: {
            
                $this->createDocument($in, $action);
                break;
                
            }
            
            default: {

                /**
                 * Не выполнять ни каких действий.
                */
                            
            }    
            
        }
        
        return $this;
        
    }
    
    /**
     * Функция установки объекта DomDocument.
     * @param    $HXml        DomDocument
     * @param    $getRoot    boolean
     * @return    boolean
     */
    function &setHandler(&$HXml, $getRoot = true) {
        
        if($getRoot) {
            
            $this->getRoot();
            
        }
        
        $this->XmlHandler    = &$HXml;
        return true;
        
    }
    
    
    /**
     * Функция возвращает объект документа.
     * @return DomDocument
     */
    function &getHandler() {

        return $this->XmlHandler;

    }

    /**
     * Функция загрузки документа.
     * Выполняет действие в зависимости от переданной опции.
     * @param    $in        string
     * @param    $action    int
     * @return    DomDocument
     */
    function load($in = '', $action = 1) {

        if(empty($in)) {
        
            return new Exception('Web.Xml.Empty-In-Parameter');
            
        }
        
        switch($action) {
            
            case XMLI_LOAD_FILE: {
                
                $this->XmlHandler    = domxml_open_mem(
                    file_get_contents($in),
                    DOMXML_LOAD_PARSING + //0
                    DOMXML_LOAD_COMPLETE_ATTRS + //8
                    DOMXML_LOAD_SUBSTITUTE_ENTITIES + //4
                    DOMXML_LOAD_DONT_KEEP_BLANKS, //16
                    $error
                );
                break;
                
            }
            
            case XMLI_LOAD_TEXT: {

                $this->XmlHandler    = domxml_open_mem(
                    $in,
                    DOMXML_LOAD_PARSING + //0
                    DOMXML_LOAD_COMPLETE_ATTRS + //8
                    DOMXML_LOAD_SUBSTITUTE_ENTITIES + //4
                    DOMXML_LOAD_DONT_KEEP_BLANKS, //16
                    $error
                );
                break;
                
            }
            
            default: {
                
                return new Exception('Web.Xml.unknown-action');

            }
            
        }
        
        return true;
        
    }
    
    /**
     * Функция создания документа.
     * @return    boolean
     */
    function createDocument($version = '1.0', $encoding = 'windows-1251') {

        $sXml    = "<?xml version=\"{$version}\" encoding=\"{$encoding}\"?>";
        
        $this->load($sXml);
        return true;
        
    }

    /**
     * Назначение XSL шаблона для обработки XML документа.
     * @return    boolean
     */
    function setXslTemplate($path) {

        if(!is_object($this->rootNode)) {
        
            $this->getRoot();
                
        }
        
        $xipi    = $this->XmlHandler->create_processing_instruction(
            'xml-stylesheet', 
            'type="text/xsl" href="'.$path.'"'
        );
        
        $this->XmlHandler->insert_before($xipi, $this->rootNode);
        
    }

    /**
     * Преобразование XML.
     * @return    string
     */
    function xsltProcess($template, $indent = false) {

        $xslproc    = domxml_xslt_stylesheet_file($template);
        $result        = $xslproc->Process($this->XmlHandler);
        return $result->dump_mem($indent);
        
    }

    /**
     * Выполнить XPath запрос.
     * @return    DomNode
     */
    function &query($query) {

        $this->xPath = $this->XmlHandler->xpath_new_context(
            $this->XmlHandler
        );

        $result    = $this->xPath->xpath_eval($query);
        $this->resultNodes    = $result->nodeset;
        
        return $this->resultNodes;
        
    }

    /**
     * Получить элемент верхнего уровня.
     * @return    DomNode
     */
    function &getRoot() {

        $this->rootNode    = $this->XmlHandler->document_element();
        return $this->rootNode;
        
    }
    
    /**
     * Подключение XML документов в текущий документ при помощи технологии XInclude, XPointer.
     * Пример: 
     * $XmlIObject->includeXml(
     *        $XmlIObject->rootNode, 
     *        'base-other',
     *        'http://www.example.com/base.xml#root-node/other-node',
     *        'Произошла ошибка при подключении удаленного XML документа'
     * );
     *
     * @param    &$node        DomNode
     * @param    $name        string
     * @param    $uri        string
     * @param    $fallback    string
     *
     * @return    DomNode
     */
    function &includeXml(&$node, $name, $uri, $fallback = '') {

        if(!is_object($this->rootNode->type)) {

            $this->getRoot();
            
        }
        
        $this->rootNode->set_namespace(XMLI_XINCLUDE_NS, XMLI_XINCLUDE_PREFIX);
            
        $incnode    = $this->XmlHandler->create_element_ns(
            XMLI_XINCLUDE_NS,
            $name,
            XMLI_XINCLUDE_PREFIX
        );
        $incnode->set_attribute('href', $uri);
        
        $fbnode        = $this->XmlHandler->create_element_ns(
            XMLI_XINCLUDE_NS,
            'fallback',
            XMLI_XINCLUDE_PREFIX
        );
        
        $ernode        = $this->XmlHandler->create_element('error');
        $ernode->append_child(
            $this->XmlHandler->create_text_node(
                'XmlI: невозможно подключить XML данные из удаленного источника.'
            )
        );
        
        $fbnode->append_child($ernode);
        $incnode->append_child($fbnode);
        
        $node->append_child($incnode);
        $this->XmlHandler->xinclude();
        
        return $incnode;
        
    }
    
    /**
     * Получить контент XML документа.
     * @return    string
     */
    function source() {

        return $this->XmlHandler->dump_mem();
        
    }

    /**
     * Получить все узлы принадлежащие переданному элементу.
     * 
     * @param    &$node        DomNode
     * @param    $index        int
     * @param    $types        int
     *
     * @return    array
     */
    function &getNodes(&$node, $index = 1, $types = 1) {

        switch($index) {
        
            case XMLI_ASSOC_KEYS: {
            
                return $this->getNodesByAssocKeys($node, $types);
                
                break;
            }
            
            default: {
            
                return $this->getNodesByNumberKeys($node, $types);
                    
            }
            
        }

        return false;
        
    }

    /**
     * Получить все узлы принадлежащие переданному элементу в виде пронумерованного массива.
     * 
     * @param    &$node        DomNode
     * @param    $types        int
     *
     * @return    array
     */
    function &getNodesByNumberKeys(&$node, $types = 1) {

        $nodes    = $node->child_nodes();
        
        for($i = 0; $i < sizeof($nodes); $i++) {
        
            if($nodes[$i]->type == $types) {
            
                $listNodes[]    = & $nodes[$i];
                    
            }    
            
        }
        
        return $listNodes;
        
    }

    /**
     * Получить все узлы принадлежащие переданному элементу в виде ассоциативного массива.
     * 
     * @param    &$node        DomNode
     * @param    $types        int
     *
     * @return    array
     */
    function &getNodesByAssocKeys(&$node, $types = 1) {

        if(!is_object($node)) {
            
            dump("Is not a node.");
            dump($node);
            exit;
                
        }
        
        $nodes    = $node->child_nodes();

        for($i = 0; $i < sizeof($nodes); $i++) {
        
            if($nodes[$i]->type == $types) {
            
                $listNodes[$nodes[$i]->tagname][]    = &$nodes[$i];
                    
            }
            
        }
        
        return $listNodes;
        
    }

    /**
     * Получить текст принадлежащий элементу.
     * 
     * @param    &$node        DomNode
     *
     * @return    string
     */
    function content(&$node) {

        return $node->get_content();
        
    }
    
    /**
     * Получить все атрибуты переданного элемента.
     * 
     * @param    &$node        DomNode
     * @param    $index        int
     *
     * @return    array
     */
    function &attributes(&$node, $index = 1) {

        switch($index) {
            
            case XMLI_ASSOC_KEYS: {
            
                return $this->attributesByAssocKeys($node);
                break;
                
            }
            
            default: {
            
                return $this->attributesByNumberKeys($node);
                
            }
            
        }
        
    }
    
    /**
     * Получить все атрибуты переданного элемента в массиве с ассоциативными ключами.
     * 
     * @param    &$node        DomNode
     *
     * @return    array
     */
    function &attributesByAssocKeys(&$node) {

        $attributes    = $node->attributes();
        
        for($i = 0; $i < sizeof($attributes); $i++) {
        
            $listAttr[$attributes[$i]->name]    = $attributes[$i]->value;
            
        }
        
        return $listAttr;
    }
    
    /**
     * Получить все атрибуты переданного элемента в массиве с пронумерованными ключами.
     * 
     * @param    &$node        DomNode
     *
     * @return    array
     */
    function &attributesByNumberKeys(&$node) {

        $attributes    = $node->attributes();
        
        for($i = 0; $i < sizeof($attributes); $i++) {
        
            $listAttr[]    = $attributes[$i]->value;
            
        }
        
        return $listAttr;
    }

    /**
     * Создать корневой элемент.
     * 
     * @param    $name        string
     * @param    $text        string
     * @param    $attr        array
     * @param    $cdata        boolean
     * @param    $ns            string
     * @param    $prefix        string
     *
     * @return    DomNode
     */
    function &setRoot($name, $text = '', $attr = array(), $cdata = false, $ns = '', $prefix = '') {

        $this->rootNode    = $this->createNode($name, $text, $attr, $cdata, $ns, $prefix);
        $this->XmlHandler->append_child($this->rootNode);
        return $this->rootNode;
        
    }

    /**
     * Создать элемент в корне.
     * 
     * @param    $name        string
     * @param    $text        string
     * @param    $attr        array
     * @param    $cdata        boolean
     * @param    $ns            string
     * @param    $prefix        string
     *
     * @return    DomNode
     */
    function &createInRoot($name, $text = '', $attr = array(), $cdata = false, $ns = '', $prefix = '') {

        $xinode    = $this->createNode($name, $text, $attr, $cdata, $ns, $prefix);
        $this->append($this->rootNode, $xinode);
        return $xinode;

    }

    /**
     * Создать элемент.
     * 
     * @param    $name        string
     * @param    $text        string
     * @param    $attr        array
     * @param    $cdata        boolean
     * @param    $ns            string
     * @param    $prefix        string
     *
     * @return    DomNode
     */
    function &createNode($name, $text = '', $attr = array(), $cdata = false, $ns = '', $prefix = '') {

        if(empty($ns)) {
        
            $xinode    = $this->XmlHandler->create_element($name);
            
        } else {
        
            if(empty($prefix)) {
            
                $xinode    = $this->XmlHandler->create_element_ns($ns, $name);
                
            } else {
            
                $xinode    = $this->XmlHandler->create_element_ns($ns, $name, $prefix);
                    
            }
            
        }
        
        if(!empty($text)) {

            switch($cdata) {
                
                case true: {
            
                    $xinode->append_child(
                        $this->XmlHandler->create_cdata_section($text)
                    );
                    
                    break;
                    
                }
                
                default: {
                
                    $xinode->append_child(
                        $this->XmlHandler->create_text_node($text)
                    );
                    
                }
                
            }
            
        }
        
        if(is_array($attr)) {
            
            if(sizeof($attr) != 0) {
                
                foreach($attr as $key => $value) {
                
                    $xinode->set_attribute($key, $value);
                    
                }
                
            }
            
        }
        
        return $xinode;

    }

    /**
     * Присоединить элемент `$node` к эелементу `$to`.
     * 
     * @param    &$to        DomNode
     * @param    &$node        DomNode
     *
     * @return    boolean
     */
    function &append(&$to, &$node) {

        $to->append_child($node);
        return true;

    }

    /**
     * Сохранить документ.
     * 
     * @param    $filename    string
     * @param    $compress    boolean
     * @param    $mode        boolean
     *
     * @return    string
     */
    function save($filename, $compress = false, $mode = true) {

        $this->XmlHandler->dump_file(
            "{$this->SavePath}/{$file}", $compress, $mode
        );
        
        return "{$this->SavePath}/{$file}";
        
    }
    
    function destroy() {

        $this->rootNode        = null;
        $this->XmlHandler    = null;
        $this->resultNodes    = null;
        $this                = null;
        
    }
    
}





--------------------
Один из розовых плюшевых-всадников апокалипсиса... очень злой...

Семь кругов ада для новых элементов языка
Мои разрозненные мысли
PM MAIL WWW ICQ Skype GTalk   Вверх
IZ@TOP
Дата 30.8.2005, 21:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Панда-бир!
****


Профиль
Группа: Участник
Сообщений: 4795
Регистрация: 3.2.2003
Где: Бамбуковый лес

Репутация: нет
Всего: 73



Примеры работы:

Код

$xml = new XmlI('/home/exampl_com/public_html/conf.xml', XMLI_LOAD_FILE);
$xml->getRoot();

// Выбрать все ноды (типа эелемент) принадлежащие корню в ассоциативный массив.
$nodes = $xml->getNodes($xml->rootNode, XMLI_ASSOC_KEYS, XML_ELEMENT_NODE);
// При чем по умолчанию все ноды выбираются в ассоциативный массив, поэтому в директиве XML_ELEMENT_NODE необходимость отсутствует.

// $nodes = array(
// 'node-1' => array(
// [0] => 'node-1' // domnode object...
// etc...
// )
// )

$attr = $xml->attributes($nodes['node-1'][0], XMLI_ASSOC_KEYS);

// Создание ноды

$newnode = $xml->createNode('node-name', 'text in node - может быть пустым',
 array('attribute' => 'la-la-la'), true (is cdata section), 'my-namespace', 'my-namespace-prefix');

$xml->append($xml->rootNode, $newnode);

// Присоединение одной ноды к другой.

// Ну типа того же что и в первом случае.


А далее смотрите комменты. Все примерно ясно должно быть.


--------------------
Один из розовых плюшевых-всадников апокалипсиса... очень злой...

Семь кругов ада для новых элементов языка
Мои разрозненные мысли
PM MAIL WWW ICQ Skype GTalk   Вверх
Irokez
Дата 30.8.2005, 21:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


индеец
***


Профиль
Группа: Участник Клуба
Сообщений: 1180
Регистрация: 20.10.2004

Репутация: нет
Всего: 53



а чем DOM не устроил?
PM   Вверх
IZ@TOP
Дата 30.8.2005, 22:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Панда-бир!
****


Профиль
Группа: Участник
Сообщений: 4795
Регистрация: 3.2.2003
Где: Бамбуковый лес

Репутация: нет
Всего: 73



Irokez, незнаю... как то криво легло под 4 РНР: половина функций не так работало... в общем не понятно...

К тому же я не про основу, а про саму реализацию обработки данных.
Добавлено @ 22:44
Хотя, можно было бы и под DOM переписать.


--------------------
Один из розовых плюшевых-всадников апокалипсиса... очень злой...

Семь кругов ада для новых элементов языка
Мои разрозненные мысли
PM MAIL WWW ICQ Skype GTalk   Вверх
Sardar
Дата 31.8.2005, 00:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бегун
****


Профиль
Группа: Модератор
Сообщений: 6986
Регистрация: 19.4.2002
Где: Нидерланды, Groni ngen

Репутация: нет
Всего: 317



ИМXО под PHP5 есть SimpleXML, вещь очень удобная, без потерь конвертируеться в DOM и обратно(внутренне по сути одно и тоже), понял что идеальный софт, «ещё лучше» не сделать smile
Кстати как выполняеться валидация? DTD? Опять же ИМXО проще и удобней RelaxNG пока не видел))

Когда то сам писал свой XML парсер(на SAX поставлен)/валидатор/процессор под PHP4, софт с интерпретаторм вылетал с "системной ошибкой". Потому и перешёл на PHP5, много завязанно на XML.


--------------------
 Опыт - сын ошибок трудных  © А. С. Пушкин
 Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik
 Оценить мои качества можно тут.
PM   Вверх
Ignat
Дата 31.8.2005, 08:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Флудератор
****


Профиль
Группа: Экс. модератор
Сообщений: 4030
Регистрация: 19.4.2004
Где: غيليندزيك مدينة

Репутация: нет
Всего: 73



Извините, не следил, за разработкой. CMS пишете заведомо на PHP5?
Тогда действительно нужно SimpleXML заюзать.


--------------------
Теперь при чем :P
PM   Вверх
IZ@TOP
Дата 1.9.2005, 20:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Панда-бир!
****


Профиль
Группа: Участник
Сообщений: 4795
Регистрация: 3.2.2003
Где: Бамбуковый лес

Репутация: нет
Всего: 73



Ignat, да я об этом думал. Конечно SimpleXML проще и удобней в использовании, тут даже спорить ни кто не будет.




--------------------
Один из розовых плюшевых-всадников апокалипсиса... очень злой...

Семь кругов ада для новых элементов языка
Мои разрозненные мысли
PM MAIL WWW ICQ Skype GTalk   Вверх
Wowa
Дата 23.2.2007, 12:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
Group Icon


Профиль
Группа: Админ
Сообщений: 15017
Регистрация: 14.9.2000
Где: Винград

Репутация: нет
Всего: 290



Ну вот, на этом и решим. SimpleXML.
PM WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Vingrad CMS | Следующая тема »


 




[ Время генерации скрипта: 0.1609 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.