' . "\n";
+                    echo '
';
+                }
+
+                if (isset($_POST['HistoryDifferences2'])) {
+                    $lines1 = array(strip_tags($oldContent)); //without <> tags
+                    $lines2 = array(strip_tags($version_new['content'])); //without <> tags
+                    $diff = new Text_Diff($lines1, $lines2);
+                    $renderer = new Text_Diff_Renderer_inline();
+                    echo ''.$renderer->render($diff); // Code inline
+                    echo '
' . "\n";
+                    echo '
';
+                    echo  '';
+                    echo ' ';
+                    echo ''.get_lang('WikiDiffAddedTex').'  ';
+                    echo ''.get_lang('WikiDiffDeletedTex').'  ';
+                    echo ' ';
+                    echo ' 
';
+                }
+            }
+        }
+    }
+
+    /**
+     * Get stat tables
+     */
+    public function getStatsTable()
+    {
+        $_course = $this->courseInfo;
+        $session_id = $this->session_id;
+        $groupId = $this->group_id;
+
+        echo '
'.get_lang('More').'
';
+        echo '
';
+        echo '  ';
+        echo '    ';
+        echo '      ';
+        echo '     ';
+        echo '    ';
+        echo '      ';
+        echo ' ';
+        echo '';
+        echo '';
+        // Submenu Statistics
+        if (api_is_allowed_to_edit(false,true) || api_is_platform_admin()) {
+            echo ''.get_lang('Statistics').'  ';
+        }
+        echo '       ';
+        echo'     ';
+        echo '   ';
+        echo '
';
+    }
+
+    /**
+     * Kind of controller
+     * @param string $action
+     */
+    public function handleAction($action)
+    {
+        $page = $this->page;
+
+        switch ($action) {
+            case 'export_to_pdf':
+                if (isset($_GET['wiki_id'])) {
+                    self::export_to_pdf($_GET['wiki_id'], api_get_course_id());
+                    exit;
+                }
+                break;
+            case 'export2doc':
+                if (isset($_GET['doc_id'])) {
+                    $export2doc = self::export2doc($_GET['doc_id']);
+                    if ($export2doc) {
+                        self::setMessage(
+                            Display::display_confirmation_message(
+                                get_lang('ThePageHasBeenExportedToDocArea'),
+                                false,
+                                true
+                            )
+                        );
+                    }
+                }
+                break;
+            case 'restorepage':
+                self::restorePage();
+                break;
+            case 'more':
+                self::getStatsTable();
+                break;
+            case 'statistics':
+                self::getStats();
+                break;
+            case 'mactiveusers':
+                self::getActiveUsers($action);
+                break;
+            case 'usercontrib':
+                self::getUserContributions($_GET['user_id'], $action);
+                break;
+            case 'mostchanged':
+                $this->getMostChangedPages($action);
+                break;
+            case 'mvisited':
+                self::getMostVisited();
+                break;
+            case 'wanted':
+                $this->getWantedPages();
+                break;
+            case 'orphaned':
+                self::getOrphaned();
+                break;
+            case 'mostlinked':
+                self::getMostLinked();
+                break;
+            case 'delete':
+                self::deletePageWarning($page);
+                break;
+            case 'deletewiki':
+                $title = '
'.get_lang('DeleteWiki').'
';
+                if (api_is_allowed_to_edit(false,true) || api_is_platform_admin()) {
+                    $message = get_lang('ConfirmDeleteWiki');
+                    $message .= '
+                        '.get_lang('No').' 
+                          |  
+                        '.get_lang('Yes').' 
+                    
';
+
+                    if (!isset($_GET['delete'])) {
+                        self::setMessage($title.Display::display_warning_message($message, false, true));
+                    }
+                } else {
+                    self::setMessage(Display::display_normal_message(get_lang("OnlyAdminDeleteWiki"), false, true));
+                }
+
+                if (api_is_allowed_to_edit(false, true) || api_is_platform_admin()) {
+                    if (isset($_GET['delete']) && $_GET['delete'] == 'yes') {
+                        $return_message = self::delete_wiki();
+                        self::setMessage(Display::display_confirmation_message($return_message, false, true));
+                        $this->redirectHome();
+                    }
+                }
+                break;
+            case 'searchpages':
+                self::getSearchPages($action);
+                break;
+            case 'links':
+                self::getLinks($page);
+                break;
+            case 'addnew':
+                if (api_get_session_id()!=0 && api_is_allowed_to_session_edit(false,true)==false) {
+                    api_not_allowed();
+                }
+                echo '
'.get_lang('AddNew').'
';
+                echo '
';
+                //first, check if page index was created. chektitle=false
+                if (self::checktitle('index')) {
+                    if (api_is_allowed_to_edit(false,true) ||
+                        api_is_platform_admin() ||
+                        GroupManager::is_user_in_group(api_get_user_id(), api_get_group_id())
+                    ) {
+                        self::setMessage(Display::display_normal_message(get_lang('GoAndEditMainPage'), false, true));
+                    } else {
+                        self::setMessage(Display::display_normal_message(get_lang('WikiStandBy'), false, true));
+                    }
+                } elseif (self::check_addnewpagelock()==0 && (api_is_allowed_to_edit(false, true)==false || api_is_platform_admin()==false)) {
+                    self::setMessage(Display::display_error_message(get_lang('AddPagesLocked'), false, true));
+                } else {
+                    if (api_is_allowed_to_edit(false,true) ||
+                        api_is_platform_admin() ||
+                        GroupManager::is_user_in_group(api_get_user_id(), api_get_group_id()) ||
+                        $_GET['group_id'] == 0
+                    ) {
+                        self::display_new_wiki_form();
+                    } else {
+                        self::setMessage(Display::display_normal_message(get_lang('OnlyAddPagesGroupMembers'), false, true));
+                    }
+                }
+                break;
+            case 'show':
+                self::display_wiki_entry($page);
+                break;
+            case 'showpage':
+                self::display_wiki_entry($page);
+                //self::setMessage(Display::display_error_message(get_lang('MustSelectPage'));
+                break;
+            case 'edit':
+                self::editPage();
+                break;
+            case 'history':
+                self::getHistory();
+                break;
+            case 'recentchanges':
+                self::recentChanges($page, $action);
+                break;
+            case 'allpages':
+                self::allPages($action);
+                break;
+            case 'discuss':
+                //self::setMessage(Display::display_confirmation_message(get_lang('CommentAdded'));
+                self::getDiscuss($page);
+                break;
+            case 'export_to_doc_file':
+                self::exportTo($_GET['id'], 'odt');
+                exit;
+                break;
+        }
+    }
+
+    /**
+     * @param string $message
+     */
+    public function setMessage($message)
+    {
+        $messagesArray = Session::read('wiki_message');
+        if (empty($messagesArray)) {
+            $messagesArray = array($message);
+        } else {
+            $messagesArray[] = $message;
+        }
+
+        Session::write('wiki_message', $messagesArray);
+    }
+
+    /**
+     *  Get messages
+     * @return string
+     */
+    public function getMessages()
+    {
+        $messagesArray = Session::read('wiki_message');
+        $messageToString = null;
+        if (!empty($messagesArray)) {
+            foreach ($messagesArray as $message) {
+                $messageToString .= $message.'
';
+            }
+        }
+        Session::erase('wiki_message');
+
+        return $messageToString;
+    }
+
+    /**
+     * Redirect to home
+     */
+    public function redirectHome()
+    {
+        $redirectUrl = $this->url.'&action=showpage&title=index';
+        header('Location: '.$redirectUrl);
+        exit;
+    }
+
+    /**
+     * Export wiki content in a odf
+     * @param int $id
+     * @param string int
+     * @return bool
+     */
+    public function exportTo($id, $format = 'doc')
+    {
+        $data = self::get_wiki_data($id);
+        if (!empty($data['content'])) {
+            global $app;
+            $content = $app['chamilo.filesystem']->convertRelativeToAbsoluteUrl($data['content']);
+            $filePath = $app['chamilo.filesystem']->putContentInTempFile($content, $data['reflink'], 'html');
+            $convertedFile = $app['chamilo.filesystem']->transcode($filePath, $format);
+
+            DocumentManager::file_send_for_download($convertedFile);
+        }
+        return false;
+    }
+}
+
diff --git a/src/ChamiloLMS/Component/DataFilesystem/DataFilesystem.php b/src/ChamiloLMS/Component/DataFilesystem/DataFilesystem.php
index c083170f47..bd48a34d0f 100644
--- a/src/ChamiloLMS/Component/DataFilesystem/DataFilesystem.php
+++ b/src/ChamiloLMS/Component/DataFilesystem/DataFilesystem.php
@@ -6,6 +6,10 @@ use Symfony\Component\Finder\Finder;
 use Symfony\Component\Finder\SplFileInfo;
 use Symfony\Component\Filesystem\Filesystem;
 use Symfony\Component\Console;
+use Unoconv\Unoconv;
+use Sunra\PhpSimple\HtmlDomParser;
+use ChamiloLMS\Component\Editor\Connector;
+use ChamiloLMS\Component\Editor\Driver\CourseDriver;
 
 /**
  * @todo use Gaufrette to manage course files (some day)
@@ -24,11 +28,15 @@ class DataFilesystem
     /**
      * @param array $paths
      * @param Filesystem $filesystem
+     * @param Unoconv $unoconv
      */
-    public function __construct($paths, Filesystem $filesystem)
+    public function __construct($paths, Filesystem $filesystem, Connector $editor, $unoconv = null)
     {
         $this->paths = $paths;
         $this->fs = $filesystem;
+        $this->unoconv = $unoconv;
+        $this->editor = $editor;
+        $this->editor->setDriver('CourseDriver');
     }
 
     /**
@@ -140,4 +148,92 @@ class DataFilesystem
         $styleSheetFolder = $this->paths['root_sys'].'main/css';
         return $finder->directories()->depth('== 0')->in($styleSheetFolder);
     }
+
+    /**
+     * Creates a empty file inside the temp folder
+     * @param string $fileName
+     * @param string $extension
+     * @return string
+     */
+    public function createTempFile($fileName = null, $extension = null)
+    {
+        if (empty($fileName)) {
+            $fileName = mt_rand();
+        }
+        if (!empty($extension)) {
+            $extension = ".$extension";
+        }
+        $filePath = $this->paths['sys_temp_path'].$fileName.$extension;
+        $this->fs->touch($filePath);
+        if ($this->fs->exists($filePath)) {
+            return $filePath;
+        }
+        return null;
+    }
+
+    /**
+     * Converts ../courses/ABC/document/file.jpg to
+     * http://chamilo/courses/ABC/document/file.jpg
+     * @param string $content
+     * @return string
+     */
+    public function convertRelativeToAbsoluteUrl($content)
+    {
+        /** @var CourseDriver $courseDriver */
+        $courseDriver = $this->editor->getDriver('CourseDriver');
+
+        $dom = HtmlDomParser::str_get_html($content);
+        //var_dump($this->editor->getDrivers());
+        /** @var \simple_html_dom_node $image */
+        foreach ($dom->find('img') as $image) {
+            $image->src = str_replace(
+                $courseDriver->getCourseDocumentRelativeWebPath(),
+                $courseDriver->getCourseDocumentWebPath(),
+                $image->src
+            );
+        }
+        return $dom;
+    }
+
+    /**
+     * Save string in a temp file
+     * @param string $content
+     * @param string $fileName
+     * @param string $extension
+     *
+     * @return string file path
+     */
+    public function putContentInTempFile($content, $filename = null, $extension = null)
+    {
+        $file = $this->createTempFile($filename, $extension);
+        if (!empty($file)) {
+            $this->fs->dumpFile($file, $content);
+            return $file;
+        }
+        return null;
+    }
+
+    /**
+     * @param string $filePath
+     * @param string $format
+     * @return string
+     */
+    public function transcode($filePath, $format)
+    {
+        if ($this->fs->exists($filePath)) {
+            $fileInfo = pathinfo($filePath);
+            $fileName = $fileInfo['filename'];
+            $newFilePath = str_replace(
+                $fileInfo['basename'],
+                $fileName.'.'.$format, $filePath
+            );
+            $this->unoconv->transcode($filePath, $format, $newFilePath);
+            if ($this->fs->exists($newFilePath)) {
+                return $newFilePath;
+
+            }
+        }
+        return false;
+    }
+
 }
diff --git a/src/ChamiloLMS/Component/Editor/Connector.php b/src/ChamiloLMS/Component/Editor/Connector.php
index a145f6e087..d79be21e5e 100644
--- a/src/ChamiloLMS/Component/Editor/Connector.php
+++ b/src/ChamiloLMS/Component/Editor/Connector.php
@@ -170,7 +170,6 @@ class Connector
         return $driverUpdated;
     }
 
-
     /**
      * Get default driver settings.
      * @return array
@@ -269,19 +268,35 @@ class Connector
             )
         );
 
-        foreach ($this->getDriverList() as $driverName) {
-            $driverClass = $this->getDriverClass($driverName);
-            /** @var Driver $driver */
-            $driver = new $driverClass();
-            $driver->setName($driverName);
-            $driver->setConnector($this);
-            $this->addDriver($driver);
-        }
+        $this->setDrivers();
 
         $opts['roots'] = $this->getRoots();
         return $opts;
     }
 
+    /**
+     * Set drivers from list
+     */
+    public function setDrivers()
+    {
+        foreach ($this->getDriverList() as $driverName) {
+            $this->setDriver($driverName);
+        }
+    }
+
+    /**
+     * Sets a driver.
+     * @param string $driverName
+     */
+    public function setDriver($driverName)
+    {
+        $driverClass = $this->getDriverClass($driverName);
+        /** @var Driver $driver */
+        $driver = new $driverClass();
+        $driver->setName($driverName);
+        $driver->setConnector($this);
+        $this->addDriver($driver);
+    }
 
     /**
      * Simple function to demonstrate how to control file access using "accessControl" callback.
diff --git a/src/ChamiloLMS/Component/Editor/Driver/CourseDriver.php b/src/ChamiloLMS/Component/Editor/Driver/CourseDriver.php
index 428356f8bb..5e15552134 100644
--- a/src/ChamiloLMS/Component/Editor/Driver/CourseDriver.php
+++ b/src/ChamiloLMS/Component/Editor/Driver/CourseDriver.php
@@ -22,7 +22,7 @@ class CourseDriver extends Driver
             return array(
                 'driver' => 'CourseDriver',
                 'path' => $this->getCourseDocumentSysPath(),
-                'URL' => $this->getCourseDocumentWebPath(),
+                'URL' => $this->getCourseDocumentRelativeWebPath(),
                 'accessControl' => array($this, 'access'),
                 'alias' => $alias,
                 'attributes' => array(
@@ -58,7 +58,7 @@ class CourseDriver extends Driver
     /**
      * @return string
      */
-    public function getCourseDocumentWebPath()
+    public function getCourseDocumentRelativeWebPath()
     {
         $url = null;
         if (isset($this->connector->course)) {
@@ -68,6 +68,20 @@ class CourseDriver extends Driver
         return $url;
     }
 
+
+    /**
+     * @return string
+     */
+    public function getCourseDocumentWebPath()
+    {
+        $url = null;
+        if (isset($this->connector->course)) {
+            $directory = $this->connector->course->getDirectory();
+            $url = api_get_path(WEB_DATA_COURSE_PATH).$directory.'/document/';
+        }
+        return $url;
+    }
+
     /**
      * {@inheritdoc}
      */
diff --git a/src/ChamiloLMS/Component/Editor/Driver/CourseUserDriver.php b/src/ChamiloLMS/Component/Editor/Driver/CourseUserDriver.php
index 34e68524eb..e17f577b34 100644
--- a/src/ChamiloLMS/Component/Editor/Driver/CourseUserDriver.php
+++ b/src/ChamiloLMS/Component/Editor/Driver/CourseUserDriver.php
@@ -28,7 +28,7 @@ class CourseUserDriver extends CourseDriver
                     'alias' => $alias,
                     'path' => $this->getCourseDocumentSysPath().$path,
                     //'alias' => $courseInfo['code'].' personal documents',
-                    'URL' => $this->getCourseDocumentWebPath().$path,
+                    'URL' => $this->getCourseDocumentRelativeWebPath().$path,
                     'accessControl' => 'access'
                 );
             }
diff --git a/src/ChamiloLMS/Component/Editor/Driver/DropBoxDriver.php b/src/ChamiloLMS/Component/Editor/Driver/DropBoxDriver.php
index 88b8b0c4ae..987cdcb68e 100644
--- a/src/ChamiloLMS/Component/Editor/Driver/DropBoxDriver.php
+++ b/src/ChamiloLMS/Component/Editor/Driver/DropBoxDriver.php
@@ -81,7 +81,7 @@ class DropBoxDriver extends \elFinderVolumeMySQL implements InterfaceDriver
                         'alias' => 'dropbox',
                         'tmpPath' => $this->connector->paths['sys_temp_path'],
                         //'alias' => $courseInfo['code'].' personal documents',
-                        //'URL' => $this->getCourseDocumentWebPath().$path,
+                        //'URL' => $this->getCourseDocumentRelativeWebPath().$path,
                         'accessControl' => 'access'
                     );
                 }
diff --git a/vendor/autoload.php b/vendor/autoload.php
index 088c34b044..214d93da4f 100644
--- a/vendor/autoload.php
+++ b/vendor/autoload.php
@@ -4,4 +4,4 @@
 
 require_once __DIR__ . '/composer' . '/autoload_real.php';
 
-return ComposerAutoloaderInit68de3dbf4a2a3e667c00f4d8391e6581::getLoader();
+return ComposerAutoloaderInitda8df92eadc454c2aaf367aac7d7b7ce::getLoader();
diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php
index 5a1ce5546d..928767b078 100644
--- a/vendor/composer/autoload_classmap.php
+++ b/vendor/composer/autoload_classmap.php
@@ -11,10 +11,6 @@ return array(
     'Absolute_Positioner' => $baseDir . '/main/inc/lib/phpdocx/pdf/include/absolute_positioner.cls.php',
     'AbstractLink' => $baseDir . '/main/gradebook/lib/be/abstractlink.class.php',
     'Abstract_Renderer' => $baseDir . '/main/inc/lib/phpdocx/pdf/include/abstract_renderer.cls.php',
-    'Access' => $baseDir . '/main/inc/lib/access.class.php',
-    'AccessAll' => $baseDir . '/main/inc/lib/access.class.php',
-    'AccessForbidden' => $baseDir . '/main/inc/lib/access.class.php',
-    'AccessToken' => $baseDir . '/main/inc/lib/access_token.class.php',
     'Accessurleditcoursestourl' => $baseDir . '/main/inc/lib/access_url_edit_courses_to_url_functions.lib.php',
     'Accessurleditsessionstourl' => $baseDir . '/main/inc/lib/access_url_edit_sessions_to_url_functions.lib.php',
     'Accessurledituserstourl' => $baseDir . '/main/inc/lib/access_url_edit_users_to_url_functions.lib.php',
@@ -22,7 +18,6 @@ return array(
     'AddManySessionToCategoryFunctions' => $baseDir . '/main/inc/lib/add_many_session_to_category_functions.lib.php',
     'AdminPage' => $baseDir . '/main/admin/admin_page.class.php',
     'Agenda' => $baseDir . '/main/inc/lib/agenda.lib.php',
-    'AjaxController' => $baseDir . '/main/inc/lib/ajax_controller.class.php',
     'Announcement' => $baseDir . '/main/coursecopy/classes/Announcement.class.php',
     'AnnouncementEmail' => $baseDir . '/main/inc/lib/announcement_email.class.php',
     'AnnouncementManager' => $baseDir . '/main/inc/lib/announcements.inc.php',
@@ -59,14 +54,12 @@ return array(
     'Cellmap' => $baseDir . '/main/inc/lib/phpdocx/pdf/include/cellmap.cls.php',
     'Certificate' => $baseDir . '/main/inc/lib/certificate.lib.php',
     'Cezpdf' => $baseDir . '/main/inc/lib/ezpdf/class.ezpdf.php',
-    'Chamilo' => $baseDir . '/main/inc/lib/chamilo.class.php',
     'ChamiloIndexer' => $baseDir . '/main/inc/lib/search/ChamiloIndexer.class.php',
     'ChamiloSession' => $baseDir . '/main/inc/lib/chamilo_session.class.php',
     'Chat' => $baseDir . '/main/inc/lib/chat.lib.php',
     'ClassManager' => $baseDir . '/main/inc/lib/classmanager.lib.php',
     'Collator' => $vendorDir . '/symfony/intl/Symfony/Component/Intl/Resources/stubs/Collator.php',
     'ConditionalLogin' => $baseDir . '/main/inc/lib/conditional_login.class.php',
-    'Controller' => $baseDir . '/main/inc/lib/controller.class.php',
     'Converter' => $baseDir . '/main/inc/lib/system/text/converter.class.php',
     'Course' => $baseDir . '/main/coursecopy/classes/Course.class.php',
     'CourseArchiver' => $baseDir . '/main/coursecopy/classes/CourseArchiver.class.php',
@@ -74,8 +67,6 @@ return array(
     'CourseCopyAttendance' => $baseDir . '/main/coursecopy/classes/Attendance.class.php',
     'CourseCopyLearnpath' => $baseDir . '/main/coursecopy/classes/CourseCopyLearnpath.class.php',
     'CourseDescription' => $baseDir . '/main/inc/lib/course_description.lib.php',
-    'CourseEntity' => $baseDir . '/main/inc/lib/course_entity.class.php',
-    'CourseEntityRepository' => $baseDir . '/main/inc/lib/course_entity_repository.class.php',
     'CourseHome' => $baseDir . '/main/inc/lib/course_home.lib.php',
     'CourseManager' => $baseDir . '/main/inc/lib/course.lib.php',
     'CourseRecycler' => $baseDir . '/main/coursecopy/classes/CourseRecycler.class.php',
@@ -189,8 +180,6 @@ return array(
     'DummyCourseCreator' => $baseDir . '/main/coursecopy/classes/DummyCourseCreator.class.php',
     'Encoding' => $baseDir . '/main/inc/lib/system/text/encoding.class.php',
     'EncodingConverter' => $baseDir . '/main/inc/lib/system/text/encoding_converter.class.php',
-    'Entity' => $baseDir . '/main/inc/lib/entity.class.php',
-    'EntityRepository' => $baseDir . '/main/inc/lib/entity_repository.class.php',
     'EvalForm' => $baseDir . '/main/gradebook/lib/fe/evalform.class.php',
     'EvalLink' => $baseDir . '/main/gradebook/lib/be/evallink.class.php',
     'Evaluation' => $baseDir . '/main/gradebook/lib/be/evaluation.class.php',
@@ -211,7 +200,6 @@ return array(
     'FacebookApiException' => $baseDir . '/main/auth/external_login/facebook-php-sdk/src/base_facebook.php',
     'FileManager' => $baseDir . '/main/inc/lib/fileManager.lib.php',
     'FileReader' => $baseDir . '/main/inc/lib/system/io/file_reader.class.php',
-    'FileStore' => $baseDir . '/main/inc/lib/file_store.class.php',
     'FileWriter' => $baseDir . '/main/inc/lib/system/io/file_writer.class.php',
     'FillBlanks' => $baseDir . '/main/exercice/fill_blanks.class.php',
     'FlatViewDataGenerator' => $baseDir . '/main/gradebook/lib/flatview_data_generator.class.php',
@@ -364,7 +352,6 @@ return array(
     'Inline_Positioner' => $baseDir . '/main/inc/lib/phpdocx/pdf/include/inline_positioner.cls.php',
     'Inline_Renderer' => $baseDir . '/main/inc/lib/phpdocx/pdf/include/inline_renderer.cls.php',
     'IntlDateFormatter' => $vendorDir . '/symfony/intl/Symfony/Component/Intl/Resources/stubs/IntlDateFormatter.php',
-    'Javascript' => $baseDir . '/main/inc/lib/javascript.class.php',
     'Javascript_Embedder' => $baseDir . '/main/inc/lib/phpdocx/pdf/include/javascript_embedder.cls.php',
     'KeyAuth' => $baseDir . '/main/auth/key/key_auth.class.php',
     'LearnpathLink' => $baseDir . '/main/gradebook/lib/be/learnpathlink.class.php',
@@ -444,12 +431,7 @@ return array(
     'MediaQuestion' => $baseDir . '/main/exercice/media_question.class.php',
     'MessageManager' => $baseDir . '/main/inc/lib/message.lib.php',
     'Model' => $baseDir . '/main/inc/lib/model.lib.php',
-    'Model\\Course' => $baseDir . '/main/inc/lib/course.class.php',
     'Model\\Document' => $baseDir . '/main/inc/lib/document.class.php',
-    'Model\\ItemProperty' => $baseDir . '/main/inc/lib/item_property.class.php',
-    'Model\\ItemPropertyRepository' => $baseDir . '/main/inc/lib/item_property.class.php',
-    'Model\\StudentPublication' => $baseDir . '/main/inc/lib/student_publication.class.php',
-    'Model\\StudentPublicationRepository' => $baseDir . '/main/inc/lib/student_publication.class.php',
     'MultipleAnswer' => $baseDir . '/main/exercice/multiple_answer.class.php',
     'MultipleAnswerCombination' => $baseDir . '/main/exercice/multiple_answer_combination.class.php',
     'MultipleAnswerCombinationTrueFalse' => $baseDir . '/main/exercice/multiple_answer_combination_true_false.class.php',
@@ -486,7 +468,6 @@ return array(
     'PGTStorageDB' => $baseDir . '/main/auth/cas/lib/CAS/PGTStorage/pgt-db.php',
     'PGTStorageFile' => $baseDir . '/main/auth/cas/lib/CAS/PGTStorage/pgt-file.php',
     'PHP_Evaluator' => $baseDir . '/main/inc/lib/phpdocx/pdf/include/php_evaluator.cls.php',
-    'Page' => $baseDir . '/main/inc/lib/page.class.php',
     'PageController' => $baseDir . '/main/inc/lib/page.lib.php',
     'Page_Cache' => $baseDir . '/main/inc/lib/phpdocx/pdf/include/page_cache.cls.php',
     'Page_Frame_Decorator' => $baseDir . '/main/inc/lib/phpdocx/pdf/include/page_frame_decorator.cls.php',
@@ -528,15 +509,11 @@ return array(
     'QuizQuestion' => $baseDir . '/main/coursecopy/classes/QuizQuestion.class.php',
     'QuizQuestionOption' => $baseDir . '/main/coursecopy/classes/QuizQuestionOption.class.php',
     'RSSCache' => $baseDir . '/main/inc/lib/magpierss/rss_cache.inc',
-    'Redirect' => $baseDir . '/main/inc/lib/redirect.class.php',
     'Renderer' => $baseDir . '/main/inc/lib/phpdocx/pdf/include/renderer.cls.php',
     'Resource' => $baseDir . '/main/coursecopy/classes/Resource.class.php',
-    'Response' => $baseDir . '/main/inc/lib/response.class.php',
     'Result' => $baseDir . '/main/gradebook/lib/be/result.class.php',
-    'ResultSet' => $baseDir . '/main/inc/lib/result_set.class.php',
     'ResultTable' => $baseDir . '/main/gradebook/lib/fe/resulttable.class.php',
     'ResultsDataGenerator' => $baseDir . '/main/gradebook/lib/results_data_generator.class.php',
-    'Rights' => $baseDir . '/main/inc/lib/rights.lib.php',
     'S3SoapClient' => $baseDir . '/main/inc/lib/elfinder/php/elFinderVolumeS3.class.php',
     'SVG' => $vendorDir . '/mpdf/mpdf/classes/svg.php',
     'ScoreDisplay' => $baseDir . '/main/gradebook/lib/scoredisplay.class.php',
@@ -684,7 +661,6 @@ return array(
     'UniqueAnswerNoOption' => $baseDir . '/main/exercice/unique_answer_no_option.class.php',
     'Uri' => $baseDir . '/main/inc/lib/uri.class.php',
     'UrlManager' => $baseDir . '/main/inc/lib/urlmanager.lib.php',
-    'UserApiKeyManager' => $baseDir . '/main/inc/lib/user_api_key_manager.class.php',
     'UserDataGenerator' => $baseDir . '/main/gradebook/lib/user_data_generator.class.php',
     'UserForm' => $baseDir . '/main/gradebook/lib/fe/userform.class.php',
     'UserGroup' => $baseDir . '/main/inc/lib/usergroup.lib.php',
diff --git a/vendor/composer/autoload_namespaces.php b/vendor/composer/autoload_namespaces.php
index b6ead455f1..0e4beb230b 100644
--- a/vendor/composer/autoload_namespaces.php
+++ b/vendor/composer/autoload_namespaces.php
@@ -44,6 +44,7 @@ return array(
     'Symfony\\Bridge\\Monolog\\' => array($vendorDir . '/symfony/monolog-bridge'),
     'Symfony\\Bridge\\Doctrine\\' => array($vendorDir . '/symfony/doctrine-bridge'),
     'SwfTools' => array($vendorDir . '/swftools/swftools/src'),
+    'Sunra\\PhpSimple\\HtmlDomParser' => array($vendorDir . '/sunra/php-simple-html-dom-parser/Src'),
     'Silex\\Provider\\' => array($vendorDir . '/silex/web-profiler'),
     'SilexOpauth' => array($vendorDir . '/icehero/silex-opauth/src'),
     'SilexAssetic' => array($vendorDir . '/mheap/silex-assetic/src'),
diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php
index 0ab3fdf783..64e92feb92 100644
--- a/vendor/composer/autoload_real.php
+++ b/vendor/composer/autoload_real.php
@@ -2,7 +2,7 @@
 
 // autoload_real.php @generated by Composer
 
-class ComposerAutoloaderInit68de3dbf4a2a3e667c00f4d8391e6581
+class ComposerAutoloaderInitda8df92eadc454c2aaf367aac7d7b7ce
 {
     private static $loader;
 
@@ -19,9 +19,9 @@ class ComposerAutoloaderInit68de3dbf4a2a3e667c00f4d8391e6581
             return self::$loader;
         }
 
-        spl_autoload_register(array('ComposerAutoloaderInit68de3dbf4a2a3e667c00f4d8391e6581', 'loadClassLoader'), true, true);
+        spl_autoload_register(array('ComposerAutoloaderInitda8df92eadc454c2aaf367aac7d7b7ce', 'loadClassLoader'), true, true);
         self::$loader = $loader = new \Composer\Autoload\ClassLoader();
-        spl_autoload_unregister(array('ComposerAutoloaderInit68de3dbf4a2a3e667c00f4d8391e6581', 'loadClassLoader'));
+        spl_autoload_unregister(array('ComposerAutoloaderInitda8df92eadc454c2aaf367aac7d7b7ce', 'loadClassLoader'));
 
         $vendorDir = dirname(__DIR__);
         $baseDir = dirname($vendorDir);
@@ -45,14 +45,14 @@ class ComposerAutoloaderInit68de3dbf4a2a3e667c00f4d8391e6581
 
         $includeFiles = require __DIR__ . '/autoload_files.php';
         foreach ($includeFiles as $file) {
-            composerRequire68de3dbf4a2a3e667c00f4d8391e6581($file);
+            composerRequireda8df92eadc454c2aaf367aac7d7b7ce($file);
         }
 
         return $loader;
     }
 }
 
-function composerRequire68de3dbf4a2a3e667c00f4d8391e6581($file)
+function composerRequireda8df92eadc454c2aaf367aac7d7b7ce($file)
 {
     require $file;
 }
diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json
index 77d07774a5..0443c2d399 100644
--- a/vendor/composer/installed.json
+++ b/vendor/composer/installed.json
@@ -5746,5 +5746,50 @@
             "assetic",
             "silex"
         ]
+    },
+    {
+        "name": "sunra/php-simple-html-dom-parser",
+        "version": "v1.5.0",
+        "version_normalized": "1.5.0.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/sunra/php-simple-html-dom-parser.git",
+            "reference": "a0b80ace086c7e09085669205e1b3c2c9c7a453c"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/sunra/php-simple-html-dom-parser/zipball/a0b80ace086c7e09085669205e1b3c2c9c7a453c",
+            "reference": "a0b80ace086c7e09085669205e1b3c2c9c7a453c",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.3.2"
+        },
+        "time": "2013-05-04 14:32:03",
+        "type": "library",
+        "installation-source": "dist",
+        "autoload": {
+            "psr-0": {
+                "Sunra\\PhpSimple\\HtmlDomParser": "Src/"
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Sunra",
+                "email": "sunra@yandex.ru",
+                "homepage": "https://github.com/sunra"
+            }
+        ],
+        "description": "Composer adaptation of: A HTML DOM parser written in PHP5+ let you manipulate HTML in a very easy way! Require PHP 5+. Supports invalid HTML. Find tags on an HTML page with selectors just like jQuery. Extract contents from HTML in a single line.",
+        "homepage": "https://github.com/sunra/php-simple-html-dom-parser",
+        "keywords": [
+            "dom",
+            "html",
+            "parser"
+        ]
     }
 ]
diff --git a/vendor/sunra/php-simple-html-dom-parser/README.md b/vendor/sunra/php-simple-html-dom-parser/README.md
new file mode 100644
index 0000000000..4bb1f8f829
--- /dev/null
+++ b/vendor/sunra/php-simple-html-dom-parser/README.md
@@ -0,0 +1,38 @@
+php-simple-html-dom-parser
+==========================
+
+Version 1.5
+
+Adaptation for Composer and PSR-0 of:
+
+A HTML DOM parser written in PHP5+ let you manipulate HTML in a very easy way!
+Require PHP 5+.
+Supports invalid HTML.
+Find tags on an HTML page with selectors just like jQuery.
+Extract contents from HTML in a single line.
+
+http://simplehtmldom.sourceforge.net/
+
+
+Install
+-------
+
+ composer.phar require
+  - package name: "sunra/php-simple-html-dom-parser": "dev-master"
+
+
+Usage
+-----
+
+```php
+use Sunra\PhpSimple\HtmlDomParser;
+
+...
+$dom = HtmlDomParser::str_get_html( $str );
+or 
+$dom = HtmlDomParser::file_get_html( $file_name );
+
+$elems = $dom->find($elem_name);
+...
+
+```
diff --git a/vendor/sunra/php-simple-html-dom-parser/Src/Sunra/PhpSimple/HtmlDomParser.php b/vendor/sunra/php-simple-html-dom-parser/Src/Sunra/PhpSimple/HtmlDomParser.php
new file mode 100644
index 0000000000..b210580dcf
--- /dev/null
+++ b/vendor/sunra/php-simple-html-dom-parser/Src/Sunra/PhpSimple/HtmlDomParser.php
@@ -0,0 +1,20 @@
+
+
+
+
+	FootballScoresLive - Previous Results
+ 
+
+
+
+
+
+
+
+    
+
+
\ No newline at end of file
diff --git a/vendor/sunra/php-simple-html-dom-parser/Src/Sunra/PhpSimple/simplehtmldom_1_5/app/index.php b/vendor/sunra/php-simple-html-dom-parser/Src/Sunra/PhpSimple/simplehtmldom_1_5/app/index.php
new file mode 100644
index 0000000000..189aa5a156
--- /dev/null
+++ b/vendor/sunra/php-simple-html-dom-parser/Src/Sunra/PhpSimple/simplehtmldom_1_5/app/index.php
@@ -0,0 +1,144 @@
+find('html', 0);
+if ($l!==null)
+    $lang = $l->lang;
+if ($lang!='')
+    $lang = 'lang="'.$lang.'"';
+
+$charset = $html->find('meta[http-equiv*=content-type]', 0);
+$target = array();
+$query = '';
+
+if (isset($_REQUEST['query'])) {
+    $query = $_REQUEST['query'];
+    $target = $html->find($query);
+}
+
+function stat_dom($dom) {
+    $count_text = 0;
+    $count_comm = 0;
+    $count_elem = 0;
+    $count_tag_end = 0;
+    $count_unknown = 0;
+    
+    foreach($dom->nodes as $n) {
+        if ($n->nodetype==HDOM_TYPE_TEXT)
+            ++$count_text;
+        if ($n->nodetype==HDOM_TYPE_COMMENT)
+            ++$count_comm;
+        if ($n->nodetype==HDOM_TYPE_ELEMENT)
+            ++$count_elem;
+        if ($n->nodetype==HDOM_TYPE_ENDTAG)
+            ++$count_tag_end;
+        if ($n->nodetype==HDOM_TYPE_UNKNOWN)
+            ++$count_unknown;
+    }
+    
+    echo 'Total: '. count($dom->nodes).
+        ', Text: '.$count_text.
+        ', Commnet: '.$count_comm.
+        ', Tag: '.$count_elem.
+        ', End Tag: '.$count_tag_end.
+        ', Unknown: '.$count_unknown;
+}
+
+function dump_my_html_tree($node, $show_attr=true, $deep=0, $last=true) {
+    $count = count($node->nodes);
+    if ($count>0) {
+        if($last)
+            echo '
<'.htmlspecialchars($node->tag).' ';
+        else
+            echo '
<'.htmlspecialchars($node->tag).' ';
+    }
+    else {
+        $laststr = ($last===false) ? '' : ' class="last"';
+        echo '<'.htmlspecialchars($node->tag).' ';
+    }
+
+    if ($show_attr) {
+        foreach($node->attr as $k=>$v) {
+            echo ' '.htmlspecialchars($k).'="'.htmlspecialchars($node->$k).' "';
+        }
+    }
+    echo '>';
+    
+    if ($node->tag==='text' || $node->tag==='comment') {
+        echo htmlspecialchars($node->innertext);
+        return;
+    }
+
+    if ($count>0) echo "\n\n";
+    $i=0;
+    foreach($node->nodes as $c) {
+        $last = (++$i==$count) ? true : false;
+        dump_my_html_tree($c, $show_attr, $deep+1, $last);
+    }
+    if ($count>0)
+        echo " \n";
+
+    //if ($count>0) echo '</'.htmlspecialchars($node->tag).' >';
+    echo " \n";
+}
+?>
+
+
+>
+
+    
+        if ($lang!='')
+            echo '
';
+        else if ($charset)
+            echo $charset;
+        else 
+            echo '
';
+    ?>
+	
Simple HTML DOM Query Test 
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
Simple HTML DOM Test 
+    
+    
+	HTML STAT ()
+    
+	
+	
+	    
+            ob_start();
+            foreach($target as $e)
+                dump_my_html_tree($e, true);
+            ob_end_flush();
+        ?>
+	 
+
+ 
+
\ No newline at end of file
diff --git a/vendor/sunra/php-simple-html-dom-parser/Src/Sunra/PhpSimple/simplehtmldom_1_5/app/js/images/treeview-default-line.gif b/vendor/sunra/php-simple-html-dom-parser/Src/Sunra/PhpSimple/simplehtmldom_1_5/app/js/images/treeview-default-line.gif
new file mode 100644
index 0000000000..37114d3068
Binary files /dev/null and b/vendor/sunra/php-simple-html-dom-parser/Src/Sunra/PhpSimple/simplehtmldom_1_5/app/js/images/treeview-default-line.gif differ
diff --git a/vendor/sunra/php-simple-html-dom-parser/Src/Sunra/PhpSimple/simplehtmldom_1_5/app/js/images/treeview-default.gif b/vendor/sunra/php-simple-html-dom-parser/Src/Sunra/PhpSimple/simplehtmldom_1_5/app/js/images/treeview-default.gif
new file mode 100644
index 0000000000..a12ac52ffe
Binary files /dev/null and b/vendor/sunra/php-simple-html-dom-parser/Src/Sunra/PhpSimple/simplehtmldom_1_5/app/js/images/treeview-default.gif differ
diff --git a/vendor/sunra/php-simple-html-dom-parser/Src/Sunra/PhpSimple/simplehtmldom_1_5/app/js/jquery.js b/vendor/sunra/php-simple-html-dom-parser/Src/Sunra/PhpSimple/simplehtmldom_1_5/app/js/jquery.js
new file mode 100644
index 0000000000..b660baab4a
--- /dev/null
+++ b/vendor/sunra/php-simple-html-dom-parser/Src/Sunra/PhpSimple/simplehtmldom_1_5/app/js/jquery.js
@@ -0,0 +1,3363 @@
+(function(){
+/*
+ * jQuery 1.2.2b2 - New Wave Javascript
+ *
+ * Copyright (c) 2007 John Resig (jquery.com)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * $Date: 2007-12-20 14:36:56 +0100 (Don, 20 Dez 2007) $
+ * $Rev: 4251 $
+ */
+
+// Map over jQuery in case of overwrite
+if ( window.jQuery )
+	var _jQuery = window.jQuery;
+
+var jQuery = window.jQuery = function( selector, context ) {
+	// The jQuery object is actually just the init constructor 'enhanced'
+	return new jQuery.prototype.init( selector, context );
+};
+
+// Map over the $ in case of overwrite
+if ( window.$ )
+	var _$ = window.$;
+	
+// Map the jQuery namespace to the '$' one
+window.$ = jQuery;
+
+// A simple way to check for HTML strings or ID strings
+// (both of which we optimize for)
+var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/;
+
+// Is it a simple selector
+var isSimple = /^.[^:#\[\.]*$/;
+
+jQuery.fn = jQuery.prototype = {
+	init: function( selector, context ) {
+		// Make sure that a selection was provided
+		selector = selector || document;
+
+		// Handle $(DOMElement)
+		if ( selector.nodeType ) {
+			this[0] = selector;
+			this.length = 1;
+			return this;
+
+		// Handle HTML strings
+		} else if ( typeof selector == "string" ) {
+			// Are we dealing with HTML string or an ID?
+			var match = quickExpr.exec( selector );
+
+			// Verify a match, and that no context was specified for #id
+			if ( match && (match[1] || !context) ) {
+
+				// HANDLE: $(html) -> $(array)
+				if ( match[1] )
+					selector = jQuery.clean( [ match[1] ], context );
+
+				// HANDLE: $("#id")
+				else {
+					var elem = document.getElementById( match[3] );
+
+					// Make sure an element was located
+					if ( elem )
+						// Handle the case where IE and Opera return items
+						// by name instead of ID
+						if ( elem.id != match[3] )
+							return jQuery().find( selector );
+
+						// Otherwise, we inject the element directly into the jQuery object
+						else {
+							this[0] = elem;
+							this.length = 1;
+							return this;
+						}
+
+					else
+						selector = [];
+				}
+
+			// HANDLE: $(expr, [context])
+			// (which is just equivalent to: $(content).find(expr)
+			} else
+				return new jQuery( context ).find( selector );
+
+		// HANDLE: $(function)
+		// Shortcut for document ready
+		} else if ( jQuery.isFunction( selector ) )
+			return new jQuery( document )[ jQuery.fn.ready ? "ready" : "load" ]( selector );
+
+		return this.setArray(
+			// HANDLE: $(array)
+			selector.constructor == Array && selector ||
+
+			// HANDLE: $(arraylike)
+			// Watch for when an array-like object, contains DOM nodes, is passed in as the selector
+			(selector.jquery || selector.length && selector != window && !selector.nodeType && selector[0] != undefined && selector[0].nodeType) && jQuery.makeArray( selector ) ||
+
+			// HANDLE: $(*)
+			[ selector ] );
+	},
+	
+	// The current version of jQuery being used
+	jquery: "@VERSION",
+
+	// The number of elements contained in the matched element set
+	size: function() {
+		return this.length;
+	},
+	
+	// The number of elements contained in the matched element set
+	length: 0,
+
+	// Get the Nth element in the matched element set OR
+	// Get the whole matched element set as a clean array
+	get: function( num ) {
+		return num == undefined ?
+
+			// Return a 'clean' array
+			jQuery.makeArray( this ) :
+
+			// Return just the object
+			this[ num ];
+	},
+	
+	// Take an array of elements and push it onto the stack
+	// (returning the new matched element set)
+	pushStack: function( elems ) {
+		// Build a new jQuery matched element set
+		var ret = jQuery( elems );
+
+		// Add the old object onto the stack (as a reference)
+		ret.prevObject = this;
+
+		// Return the newly-formed element set
+		return ret;
+	},
+	
+	// Force the current matched set of elements to become
+	// the specified array of elements (destroying the stack in the process)
+	// You should use pushStack() in order to do this, but maintain the stack
+	setArray: function( elems ) {
+		// Resetting the length to 0, then using the native Array push
+		// is a super-fast way to populate an object with array-like properties
+		this.length = 0;
+		Array.prototype.push.apply( this, elems );
+		
+		return this;
+	},
+
+	// Execute a callback for every element in the matched set.
+	// (You can seed the arguments with an array of args, but this is
+	// only used internally.)
+	each: function( callback, args ) {
+		return jQuery.each( this, callback, args );
+	},
+
+	// Determine the position of an element within 
+	// the matched set of elements
+	index: function( elem ) {
+		var ret = -1;
+
+		// Locate the position of the desired element
+		this.each(function(i){
+			if ( this == elem )
+				ret = i;
+		});
+
+		return ret;
+	},
+
+	attr: function( name, value, type ) {
+		var options = name;
+		
+		// Look for the case where we're accessing a style value
+		if ( name.constructor == String )
+			if ( value == undefined )
+				return this.length && jQuery[ type || "attr" ]( this[0], name ) || undefined;
+
+			else {
+				options = {};
+				options[ name ] = value;
+			}
+		
+		// Check to see if we're setting style values
+		return this.each(function(i){
+			// Set all the styles
+			for ( name in options )
+				jQuery.attr(
+					type ?
+						this.style :
+						this,
+					name, jQuery.prop( this, options[ name ], type, i, name )
+				);
+		});
+	},
+
+	css: function( key, value ) {
+		// ignore negative width and height values
+		if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 )
+			value = undefined;
+		return this.attr( key, value, "curCSS" );
+	},
+
+	text: function( text ) {
+		if ( typeof text != "object" && text != null )
+			return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
+
+		var ret = "";
+
+		jQuery.each( text || this, function(){
+			jQuery.each( this.childNodes, function(){
+				if ( this.nodeType != 8 )
+					ret += this.nodeType != 1 ?
+						this.nodeValue :
+						jQuery.fn.text( [ this ] );
+			});
+		});
+
+		return ret;
+	},
+
+	wrapAll: function( html ) {
+		if ( this[0] )
+			// The elements to wrap the target around
+			jQuery( html, this[0].ownerDocument )
+				.clone()
+				.insertBefore( this[0] )
+				.map(function(){
+					var elem = this;
+
+					while ( elem.firstChild )
+						elem = elem.firstChild;
+
+					return elem;
+				})
+				.append(this);
+
+		return this;
+	},
+
+	wrapInner: function( html ) {
+		return this.each(function(){
+			jQuery( this ).contents().wrapAll( html );
+		});
+	},
+
+	wrap: function( html ) {
+		return this.each(function(){
+			jQuery( this ).wrapAll( html );
+		});
+	},
+
+	append: function() {
+		return this.domManip(arguments, true, false, function(elem){
+			if (this.nodeType == 1)
+				this.appendChild( elem );
+		});
+	},
+
+	prepend: function() {
+		return this.domManip(arguments, true, true, function(elem){
+			if (this.nodeType == 1)
+				this.insertBefore( elem, this.firstChild );
+		});
+	},
+	
+	before: function() {
+		return this.domManip(arguments, false, false, function(elem){
+			this.parentNode.insertBefore( elem, this );
+		});
+	},
+
+	after: function() {
+		return this.domManip(arguments, false, true, function(elem){
+			this.parentNode.insertBefore( elem, this.nextSibling );
+		});
+	},
+
+	end: function() {
+		return this.prevObject || jQuery( [] );
+	},
+
+	find: function( selector ) {
+		var elems = jQuery.map(this, function(elem){
+			return jQuery.find( selector, elem );
+		});
+
+		return this.pushStack( /[^+>] [^+>]/.test( selector ) || selector.indexOf("..") > -1 ?
+			jQuery.unique( elems ) :
+			elems );
+	},
+
+	clone: function( events ) {
+		// Do the clone
+		var ret = this.map(function(){
+			if ( jQuery.browser.msie && !jQuery.isXMLDoc(this) ) {
+				// IE copies events bound via attachEvent when
+				// using cloneNode. Calling detachEvent on the
+				// clone will also remove the events from the orignal
+				// In order to get around this, we use innerHTML.
+				// Unfortunately, this means some modifications to 
+				// attributes in IE that are actually only stored 
+				// as properties will not be copied (such as the
+				// the name attribute on an input).
+				var clone = this.cloneNode(true),
+					container = document.createElement("div"),
+					container2 = document.createElement("div");
+				container.appendChild(clone);
+				container2.innerHTML = container.innerHTML;
+				return container2.firstChild;
+			} else
+				return this.cloneNode(true);
+		});
+
+		// Need to set the expando to null on the cloned set if it exists
+		// removeData doesn't work here, IE removes it from the original as well
+		// this is primarily for IE but the data expando shouldn't be copied over in any browser
+		var clone = ret.find("*").andSelf().each(function(){
+			if ( this[ expando ] != undefined )
+				this[ expando ] = null;
+		});
+		
+		// Copy the events from the original to the clone
+		if ( events === true )
+			this.find("*").andSelf().each(function(i){
+				var events = jQuery.data( this, "events" );
+
+				for ( var type in events )
+					for ( var handler in events[ type ] )
+						jQuery.event.add( clone[ i ], type, events[ type ][ handler ], events[ type ][ handler ].data );
+			});
+
+		// Return the cloned set
+		return ret;
+	},
+
+	filter: function( selector ) {
+		return this.pushStack(
+			jQuery.isFunction( selector ) &&
+			jQuery.grep(this, function(elem, i){
+				return selector.call( elem, i );
+			}) ||
+
+			jQuery.multiFilter( selector, this ) );
+	},
+
+	not: function( selector ) {
+		if ( selector.constructor == String )
+			// test special case where just one selector is passed in
+			if ( isSimple.test( selector ) )
+				return this.pushStack( jQuery.multiFilter( selector, this, true ) );
+			else
+				selector = jQuery.multiFilter( selector, this );
+
+		var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
+		return this.filter(function() {
+			return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
+		});
+	},
+
+	add: function( selector ) {
+		return !selector ? this : this.pushStack( jQuery.merge( 
+			this.get(),
+			selector.constructor == String ? 
+				jQuery( selector ).get() :
+				selector.length != undefined && (!selector.nodeName || jQuery.nodeName(selector, "form")) ?
+					selector : [selector] ) );
+	},
+
+	is: function( selector ) {
+		return selector ?
+			jQuery.multiFilter( selector, this ).length > 0 :
+			false;
+	},
+
+	hasClass: function( selector ) {
+		return this.is( "." + selector );
+	},
+	
+	val: function( value ) {
+		if ( value == undefined ) {
+
+			if ( this.length ) {
+				var elem = this[0];
+
+				// We need to handle select boxes special
+				if ( jQuery.nodeName( elem, "select" ) ) {
+					var index = elem.selectedIndex,
+						values = [],
+						options = elem.options,
+						one = elem.type == "select-one";
+					
+					// Nothing was selected
+					if ( index < 0 )
+						return null;
+
+					// Loop through all the selected options
+					for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
+						var option = options[ i ];
+
+						if ( option.selected ) {
+							// Get the specifc value for the option
+							value = jQuery.browser.msie && !option.attributes.value.specified ? option.text : option.value;
+							
+							// We don't need an array for one selects
+							if ( one )
+								return value;
+							
+							// Multi-Selects return an array
+							values.push( value );
+						}
+					}
+					
+					return values;
+					
+				// Everything else, we just grab the value
+				} else
+					return (this[0].value || "").replace(/\r/g, "");
+
+			}
+
+			return undefined;
+		}
+
+		return this.each(function(){
+			if ( this.nodeType != 1 )
+				return;
+
+			if ( value.constructor == Array && /radio|checkbox/.test( this.type ) )
+				this.checked = (jQuery.inArray(this.value, value) >= 0 ||
+					jQuery.inArray(this.name, value) >= 0);
+
+			else if ( jQuery.nodeName( this, "select" ) ) {
+				var values = value.constructor == Array ?
+					value :
+					[ value ];
+
+				jQuery( "option", this ).each(function(){
+					this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
+						jQuery.inArray( this.text, values ) >= 0);
+				});
+
+				if ( !values.length )
+					this.selectedIndex = -1;
+
+			} else
+				this.value = value;
+		});
+	},
+	
+	html: function( value ) {
+		return value == undefined ?
+			(this.length ?
+				this[0].innerHTML :
+				null) :
+			this.empty().append( value );
+	},
+
+	replaceWith: function( value ) {
+		return this.after( value ).remove();
+	},
+
+	eq: function( i ) {
+		return this.slice( i, i + 1 );
+	},
+
+	slice: function() {
+		return this.pushStack( Array.prototype.slice.apply( this, arguments ) );
+	},
+
+	map: function( callback ) {
+		return this.pushStack( jQuery.map(this, function(elem, i){
+			return callback.call( elem, i, elem );
+		}));
+	},
+
+	andSelf: function() {
+		return this.add( this.prevObject );
+	},
+	
+	domManip: function( args, table, reverse, callback ) {
+		var clone = this.length > 1, elems; 
+
+		return this.each(function(){
+			if ( !elems ) {
+				elems = jQuery.clean( args, this.ownerDocument );
+
+				if ( reverse )
+					elems.reverse();
+			}
+
+			var obj = this;
+
+			if ( table && jQuery.nodeName( this, "table" ) && jQuery.nodeName( elems[0], "tr" ) )
+				obj = this.getElementsByTagName("tbody")[0] || this.appendChild( this.ownerDocument.createElement("tbody") );
+
+			var scripts = jQuery( [] );
+
+			jQuery.each(elems, function(){
+				var elem = clone ?
+					jQuery( this ).clone( true )[0] :
+					this;
+
+				// execute all scripts after the elements have been injected
+				if ( jQuery.nodeName( elem, "script" ) ) {
+					scripts = scripts.add( elem );
+				} else {
+					// Remove any inner scripts for later evaluation
+					if ( elem.nodeType == 1 )
+						scripts = scripts.add( jQuery( "script", elem ).remove() );
+
+					// Inject the elements into the document
+					callback.call( obj, elem );
+				}
+			});
+
+			scripts.each( evalScript );
+		});
+	}
+};
+
+// Give the init function the jQuery prototype for later instantiation
+jQuery.prototype.init.prototype = jQuery.prototype;
+
+function evalScript( i, elem ) {
+	if ( elem.src )
+		jQuery.ajax({
+			url: elem.src,
+			async: false,
+			dataType: "script"
+		});
+
+	else
+		jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
+
+	if ( elem.parentNode )
+		elem.parentNode.removeChild( elem );
+}
+
+jQuery.extend = jQuery.fn.extend = function() {
+	// copy reference to target object
+	var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
+
+	// Handle a deep copy situation
+	if ( target.constructor == Boolean ) {
+		deep = target;
+		target = arguments[1] || {};
+		// skip the boolean and the target
+		i = 2;
+	}
+
+	// Handle case when target is a string or something (possible in deep copy)
+	if ( typeof target != "object" && typeof target != "function" )
+		target = {};
+
+	// extend jQuery itself if only one argument is passed
+	if ( length == 1 ) {
+		target = this;
+		i = 0;
+	}
+
+	for ( ; i < length; i++ )
+		// Only deal with non-null/undefined values
+		if ( (options = arguments[ i ]) != null )
+			// Extend the base object
+			for ( var name in options ) {
+				// Prevent never-ending loop
+				if ( target === options[ name ] )
+					continue;
+
+				// Recurse if we're merging object values
+				if ( deep && options[ name ] && typeof options[ name ] == "object" && target[ name ] && !options[ name ].nodeType )
+					target[ name ] = jQuery.extend( target[ name ], options[ name ] );
+
+				// Don't bring in undefined values
+				else if ( options[ name ] != undefined )
+					target[ name ] = options[ name ];
+
+			}
+
+	// Return the modified object
+	return target;
+};
+
+var expando = "jQuery" + (new Date()).getTime(), uuid = 0, windowData = {};
+
+// exclude the following css properties to add px
+var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i;
+
+jQuery.extend({
+	noConflict: function( deep ) {
+		window.$ = _$;
+
+		if ( deep )
+			window.jQuery = _jQuery;
+
+		return jQuery;
+	},
+
+	// This may seem like some crazy code, but trust me when I say that this
+	// is the only cross-browser way to do this. --John
+	isFunction: function( fn ) {
+		return !!fn && typeof fn != "string" && !fn.nodeName && 
+			fn.constructor != Array && /function/i.test( fn + "" );
+	},
+	
+	// check if an element is in a (or is an) XML document
+	isXMLDoc: function( elem ) {
+		return elem.documentElement && !elem.body ||
+			elem.tagName && elem.ownerDocument && !elem.ownerDocument.body;
+	},
+
+	// Evalulates a script in a global context
+	globalEval: function( data ) {
+		data = jQuery.trim( data );
+
+		if ( data ) {
+			// Inspired by code by Andrea Giammarchi
+			// http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
+			var head = document.getElementsByTagName("head")[0] || document.documentElement,
+				script = document.createElement("script");
+
+			script.type = "text/javascript";
+			if ( jQuery.browser.msie )
+				script.text = data;
+			else
+				script.appendChild( document.createTextNode( data ) );
+
+			head.appendChild( script );
+			head.removeChild( script );
+		}
+	},
+
+	nodeName: function( elem, name ) {
+		return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
+	},
+	
+	cache: {},
+	
+	data: function( elem, name, data ) {
+		elem = elem == window ?
+			windowData :
+			elem;
+
+		var id = elem[ expando ];
+
+		// Compute a unique ID for the element
+		if ( !id ) 
+			id = elem[ expando ] = ++uuid;
+
+		// Only generate the data cache if we're
+		// trying to access or manipulate it
+		if ( name && !jQuery.cache[ id ] )
+			jQuery.cache[ id ] = {};
+		
+		// Prevent overriding the named cache with undefined values
+		if ( data != undefined )
+			jQuery.cache[ id ][ name ] = data;
+		
+		// Return the named cache data, or the ID for the element	
+		return name ?
+			jQuery.cache[ id ][ name ] :
+			id;
+	},
+	
+	removeData: function( elem, name ) {
+		elem = elem == window ?
+			windowData :
+			elem;
+
+		var id = elem[ expando ];
+
+		// If we want to remove a specific section of the element's data
+		if ( name ) {
+			if ( jQuery.cache[ id ] ) {
+				// Remove the section of cache data
+				delete jQuery.cache[ id ][ name ];
+
+				// If we've removed all the data, remove the element's cache
+				name = "";
+
+				for ( name in jQuery.cache[ id ] )
+					break;
+
+				if ( !name )
+					jQuery.removeData( elem );
+			}
+
+		// Otherwise, we want to remove all of the element's data
+		} else {
+			// Clean up the element expando
+			try {
+				delete elem[ expando ];
+			} catch(e){
+				// IE has trouble directly removing the expando
+				// but it's ok with using removeAttribute
+				if ( elem.removeAttribute )
+					elem.removeAttribute( expando );
+			}
+
+			// Completely remove the data cache
+			delete jQuery.cache[ id ];
+		}
+	},
+
+	// args is for internal usage only
+	each: function( object, callback, args ) {
+		if ( args ) {
+			if ( object.length == undefined )
+				for ( var name in object )
+					callback.apply( object[ name ], args );
+			else
+				for ( var i = 0, length = object.length; i < length; i++ )
+					if ( callback.apply( object[ i ], args ) === false )
+						break;
+
+		// A special, fast, case for the most common use of each
+		} else {
+			if ( object.length == undefined )
+				for ( var name in object )
+					callback.call( object[ name ], name, object[ name ] );
+			else
+				for ( var i = 0, length = object.length, value = object[0]; 
+					i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
+		}
+
+		return object;
+	},
+	
+	prop: function( elem, value, type, i, name ) {
+			// Handle executable functions
+			if ( jQuery.isFunction( value ) )
+				value = value.call( elem, i );
+				
+			// Handle passing in a number to a CSS property
+			return value && value.constructor == Number && type == "curCSS" && !exclude.test( name ) ?
+				value + "px" :
+				value;
+	},
+
+	className: {
+		// internal only, use addClass("class")
+		add: function( elem, classNames ) {
+			jQuery.each((classNames || "").split(/\s+/), function(i, className){
+				if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
+					elem.className += (elem.className ? " " : "") + className;
+			});
+		},
+
+		// internal only, use removeClass("class")
+		remove: function( elem, classNames ) {
+			if (elem.nodeType == 1)
+				elem.className = classNames != undefined ?
+					jQuery.grep(elem.className.split(/\s+/), function(className){
+						return !jQuery.className.has( classNames, className );	
+					}).join(" ") :
+					"";
+		},
+
+		// internal only, use is(".class")
+		has: function( elem, className ) {
+			return jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
+		}
+	},
+
+	// A method for quickly swapping in/out CSS properties to get correct calculations
+	swap: function( elem, options, callback ) {
+		var old = {};
+		// Remember the old values, and insert the new ones
+		for ( var name in options ) {
+			old[ name ] = elem.style[ name ];
+			elem.style[ name ] = options[ name ];
+		}
+
+		callback.call( elem );
+
+		// Revert the old values
+		for ( var name in options )
+			elem.style[ name ] = old[ name ];
+	},
+
+	css: function( elem, name, force ) {
+		if ( name == "width" || name == "height" ) {
+			var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
+		
+			function getWH() {
+				val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
+				var padding = 0, border = 0;
+				jQuery.each( which, function() {
+					padding += parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
+					border += parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
+				});
+				val -= Math.round(padding + border);
+			}
+		
+			if ( jQuery(elem).is(":visible") )
+				getWH();
+			else
+				jQuery.swap( elem, props, getWH );
+			
+			return Math.max(0, val);
+		}
+		
+		return jQuery.curCSS( elem, name, force );
+	},
+
+	curCSS: function( elem, name, force ) {
+		var ret;
+
+		// A helper method for determining if an element's values are broken
+		function color( elem ) {
+			if ( !jQuery.browser.safari )
+				return false;
+
+			var ret = document.defaultView.getComputedStyle( elem, null );
+			return !ret || ret.getPropertyValue("color") == "";
+		}
+
+		// We need to handle opacity special in IE
+		if ( name == "opacity" && jQuery.browser.msie ) {
+			ret = jQuery.attr( elem.style, "opacity" );
+
+			return ret == "" ?
+				"1" :
+				ret;
+		}
+		// Opera sometimes will give the wrong display answer, this fixes it, see #2037
+		if ( jQuery.browser.opera && name == "display" ) {
+			var save = elem.style.display;
+			elem.style.display = "block";
+			elem.style.display = save;
+		}
+		
+		// Make sure we're using the right name for getting the float value
+		if ( name.match( /float/i ) )
+			name = styleFloat;
+
+		if ( !force && elem.style[ name ] )
+			ret = elem.style[ name ];
+
+		else if ( document.defaultView && document.defaultView.getComputedStyle ) {
+
+			// Only "float" is needed here
+			if ( name.match( /float/i ) )
+				name = "float";
+
+			name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
+
+			var getComputedStyle = document.defaultView.getComputedStyle( elem, null );
+
+			if ( getComputedStyle && !color( elem ) )
+				ret = getComputedStyle.getPropertyValue( name );
+
+			// If the element isn't reporting its values properly in Safari
+			// then some display: none elements are involved
+			else {
+				var swap = [], stack = [];
+
+				// Locate all of the parent display: none elements
+				for ( var a = elem; a && color(a); a = a.parentNode )
+					stack.unshift(a);
+
+				// Go through and make them visible, but in reverse
+				// (It would be better if we knew the exact display type that they had)
+				for ( var i = 0; i < stack.length; i++ )
+					if ( color( stack[ i ] ) ) {
+						swap[ i ] = stack[ i ].style.display;
+						stack[ i ].style.display = "block";
+					}
+
+				// Since we flip the display style, we have to handle that
+				// one special, otherwise get the value
+				ret = name == "display" && swap[ stack.length - 1 ] != null ?
+					"none" :
+					( getComputedStyle && getComputedStyle.getPropertyValue( name ) ) || "";
+
+				// Finally, revert the display styles back
+				for ( var i = 0; i < swap.length; i++ )
+					if ( swap[ i ] != null )
+						stack[ i ].style.display = swap[ i ];
+			}
+
+			// We should always get a number back from opacity
+			if ( name == "opacity" && ret == "" )
+				ret = "1";
+
+		} else if ( elem.currentStyle ) {
+			var camelCase = name.replace(/\-(\w)/g, function(all, letter){
+				return letter.toUpperCase();
+			});
+
+			ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
+
+			// From the awesome hack by Dean Edwards
+			// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+
+			// If we're not dealing with a regular pixel number
+			// but a number that has a weird ending, we need to convert it to pixels
+			if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
+				// Remember the original values
+				var style = elem.style.left, runtimeStyle = elem.runtimeStyle.left;
+
+				// Put in the new values to get a computed value out
+				elem.runtimeStyle.left = elem.currentStyle.left;
+				elem.style.left = ret || 0;
+				ret = elem.style.pixelLeft + "px";
+
+				// Revert the changed values
+				elem.style.left = style;
+				elem.runtimeStyle.left = runtimeStyle;
+			}
+		}
+
+		return ret;
+	},
+	
+	clean: function( elems, context ) {
+		var ret = [];
+		context = context || document;
+		// !context.createElement fails in IE with an error but returns typeof 'object'
+		if (typeof context.createElement == 'undefined') 
+			context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
+
+		jQuery.each(elems, function(i, elem){
+			if ( !elem )
+				return;
+
+			if ( elem.constructor == Number )
+				elem = elem.toString();
+			
+			// Convert html string into DOM nodes
+			if ( typeof elem == "string" ) {
+				// Fix "XHTML"-style tags in all browsers
+				elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
+					return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area)$/i) ?
+						all :
+						front + ">" + tag + ">";
+				});
+
+				// Trim whitespace, otherwise indexOf won't work as expected
+				var tags = jQuery.trim( elem ).toLowerCase(), div = context.createElement("div");
+
+				var wrap =
+					// option or optgroup
+					!tags.indexOf("
", "" ] ||
+					
+					!tags.indexOf("", "" ] ||
+					
+					tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
+					[ 1, "" ] ||
+					
+					!tags.indexOf("", " " ] ||
+					
+				 	//  matched above
+					(!tags.indexOf(" ", "  " ] ||
+					
+					!tags.indexOf("", " " ] ||
+
+					// IE can't serialize   and 
+
+
+
+
+ PHP Simple HTML DOM Parser Manual 
+
+  
Index 
+  
+	
+	
+  
Quick Start 
+  
Top 
+	
+    
+    
+      
+         
+        $html = file_get_html ('http://www.google.com/' ); 
+         
+         
+        foreach($html->find ('img' ) as $element)  
+       echo $element->src  . '<br>' ; 
+ 
+ 
+foreach($html->find ('a' ) as $element)  
+       echo $element->href  . '<br>' ;      
+    
+    
+      
+         
+        $html = str_get_html ('<div id="hello">Hello</div><div id="world">World</div>' );
+        
+$html->find ('div', 1 )->class  = 'bar' ; 
+ 
+$html->find ('div[id=hello]', 0 )->innertext  = 'foo' ; 
+         
+        echo $html;  
+    
+    
+      
 
+         
+        echo file_get_html ('http://www.google.com/' )->plaintext ;
+				 
+				 
+      
+    
+    
+      
+         
+        $html = file_get_html ('http://slashdot.org/' ); 
+         
+         
+        foreach($html->find ('div.article' ) as $article) { 
+    $item['title' ]     = $article->find ('div.title' , 0 )->plaintext ; 
+    $item['intro' ]    = $article->find ('div.intro' , 0 )->plaintext ; 
+    $item['details' ] = $article->find ('div.details' , 0 )->plaintext ; 
+    $articles[] = $item; 
+        } 
+         
+        print_r($articles);
+      
+    
+  
+	
+  
+  
How to create HTML DOM object? 
+  
Top 
+  
+    
+    
+      
 
+        $html = str_get_html ('<html><body>Hello!</body></html>' ); 
+         
+         
+        $html = file_get_html ('http://www.google.com/' ); 
+         
+         
+        $html = file_get_html ('test.htm' );
+    
+    
+      
 
+        $html = new simple_html_dom (); 
+         
+         
+        $html->load ('<html><body>Hello!</body></html>' ); 
+         
+          
+        $html->load_file ('http://www.google.com/' ); 
+         
+          
+        $html->load_file ('test.htm' );
+    
+  
+  
+  
How to find HTML elements? 
+  
Top 
+  
+    
+    
+      
  
+        $ret = $html->find('a ' ); 
+         
+          
+        $ret = $html->find('a ', 0  ); 
+         
+          
+$ret = $html->find('a ', -1  );         
+         
+         
+$ret = $html->find('div[id] ' );         
+ 
+         
+$ret = $html->find('div[id=foo] ' );         
+      
+    
+    
+      
 
+        $ret = $html->find('#foo ' ); 
+         
+         
+        $ret = $html->find('.foo ' ); 
+         
+         
+$ret = $html->find('*[id] ' );         
+         
+         
+$ret = $html->find('a, img ' );         
+         
+         
+				$ret = $html->find('a[title], img[title] ' ); 
+      
+    
+    
+      
+				Supports these operators in attribute selectors:
+        
+          
+            Filter 
+            Description 
+           
+          
+            [attribute] 
+            Matches elements that have  the specified attribute. 
+           
+          
+              [!attribute] 
+              Matches elements that don't have  the specified attribute. 
+           
+          
+            [attribute=value] 
+            Matches elements that have the specified attribute with a certain value . 
+           
+          
+            [attribute!=value] 
+            Matches elements that don't have  the specified attribute with a certain value. 
+           
+          
+            [attribute^=value] 
+            Matches elements that have the specified attribute and it starts  with a certain value. 
+           
+          
+            [attribute$=value] 
+            Matches elements that have the specified attribute and it ends  with a certain value. 
+           
+          
+            [attribute*=value] 
+            Matches elements that have the specified attribute and it contains  a certain value. 
+           
+        
+      
+    
+    
+      
 
+        $es = $html->find('ul li ' ); 
+         
+         
+        $es = $html->find('div div div ' );  
+         
+         
+        $es = $html->find('table.hello td ' ); 
+         
+         
+        $es = $html->find(''table  td[align=center] ' ); 
+      
+    
+    
+    
+      
  
+        foreach($html->find('ul ' ) as $ul)  
+        { 
+       foreach($ul->find('li ' ) as $li)  
+       { 
+              
+       } 
+        } 
+         
+          
+        $e = $html->find('ul ', 0  )->find('li ', 0  ); 
+      
+    
+  
+  
+  
How to access the HTML element's attributes? 
+  
Top 
+  
+    
+    
+      
 
+         
+        $value = $e->href ; 
+         
+         
+        $e->href  = 'my link' ; 
+         
+         
+        $e->href  = null  ; 
+         
+          
+if(isset($e->href ))  
+        echo 'href exist!' ; 
+      
+    
+    
+      
 
+        
$ html =  str_get_html
( "<div>foo <b>bar</b></div>" ) ;  
+        $e = $html->find(
"div" , 
0 );
+        
+        echo $e->
tag ; 
+        echo $e->
outertext ; 
+        echo $e->
innertext ; 
+        echo $e->
plaintext ; 
+        
+          
+            Attribute Name 
+            Usage 
+           
+          
+            $e->tag  
+            Read or write the tag name  of element. 
+           
+          
+            $e->outertext  
+            Read or write the outer HTML text   of element. 
+           
+          
+            $e->innertext  
+            Read or write the inner HTML text   of element. 
+           
+          
+            $e->plaintext  
+            Read or write the plain text   of element. 
+           
+        
+      
 
+    
+    
+      
 
+echo $html ->plaintext ; 
+  
+ 
+        $e->outertext  = '<div class="wrap">'  . $e->outertext  . '<div> '; 
+         
+         
+        $e->outertext  = '' ; 
+         
+         
+$e->outertext  = $e->outertext  . '<div>foo <div> '; 
+ 
+ 
+$e->outertext  = '<div>foo <div> ' . $e->outertext ; 
+      
+    
+  
+  
+  
How to traverse the DOM tree? 
+  
Top 
+  
+    
+    
+      
  
+         
+         
+        echo $html->find ("#div1", 0 )->children (1 )->children (1 )->children (2 )->id ; 
+          
+        echo $html->getElementById ("div1" )->childNodes (1 )->childNodes (1 )->childNodes (2 )->getAttribute ('id' ); 
+    
+    
+      
You can also call methods with 
Camel naming convertions .
+        
+          
+             Method  
+             Description 
+           
+          
+            
+              mixed
$e->children  ( [int $index]  )  
+            Returns the Nth child object  if index  is set, otherwise return an array of children .  
+           
+          
+            
+              element
$e->parent  ()  
+            Returns the parent  of element.  
+           
+          
+            
+              element
$e->first_child  ()  
+            Returns the first child  of element, or null  if not found.  
+           
+          
+            
+              element
$e->last_child  ()  
+            Returns the last child  of element, or null  if not found.  
+           
+          
+            
+              element
$e->next_sibling  ()  
+            Returns the next sibling  of element, or null  if not found.  
+           
+          
+            
+              element
$e->prev_sibling  ()  
+            Returns the previous sibling  of element, or null  if not found.  
+           
+        
+      
+    
+    
+  
+  
+  
How to dump contents of DOM object? 
+  
Top 
+  
+    
+    
+      
 
+        $str = $html->save (); 
+         
+          
+        $html->save ('result.htm' );
+    
+    
+      
 
+        $str = $html; 
+         
+         
+        echo $html;  
+      
+    
+  
+	
+  
How to customize the parsing behavior? 
+  
Top 
+  
+    
+    
+      
 
+        function my_callback($element ) { 
+                 
+        if ($element->tag=='b' )  
+                        $element->outertext = ''; 
+        }  
+         
+         
+        $html->set_callback ('my_callback' ); 
+         
+         
+        echo $html;
+      
+    
+  
+
+  
+    Author: S.C. Chen (me578022@gmail.com)
+Original idea is from Jose Solorzano's 
HTML Parser for PHP 4 . 
+Contributions by: Contributions by: Yousuke Kumakura, Vadim Voituk, Antcs
+  
+
 
+
+