Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to easily Debug Layout Xml Warning/Error?

I got stuck on this error:

Warning: simplexml_load_string(): Entity: line 46: parser error : Comment not terminated  in */lib/Varien/Simplexml/Config.php on line 510

and

Entity: line 46: parser error : Start tag expected, '<' not found  in */lib/Varien/Simplexml/Config.php on line 510

It is clear that there is an issue in some Xml file, but really not easy for me to find out the needle in the big haystack :)

Any good practice for that? If possible I would like to find a good practice that involves use Xdebug, or some log.

It happens a lot of time in Magento to do some miss spelling.

like image 349
WonderLand Avatar asked Oct 31 '12 06:10

WonderLand


2 Answers

I think you can take a look at this article Dealing with XML errors.

This warning is related to some config.xml error, so a possible workaround to find out the exact file is to mod. the /lib/Varien/Simplexml/Config.php class.

You should modify Varien_Simplexml_Config::loadString() method:

public function loadString($string)
{
    if (is_string($string)) {
        // Enable internal errors
        libxml_use_internal_errors(true);
        $xml = simplexml_load_string($string, $this->_elementClass);
        if (false === $xml) {
            // Put breakpoint here
            $errors = libxml_get_errors();
        }
        if ($xml instanceof Varien_Simplexml_Element) {
            $this->_xml = $xml;
            return true;
        }
    } else {
        Mage::logException(new Exception('"$string" parameter for simplexml_load_string is not a string'));
    }
    return false;
}

In case the error is related to some Layout file ( Update.php line 444 warning )

You should modify Mage_Core_Model_Layout_Update::getFileLayoutUpdatesXml() method in a similar way:

public function getFileLayoutUpdatesXml($area, $package, $theme, $storeId = null)
{
    if (null === $storeId) {
        $storeId = Mage::app()->getStore()->getId();
    }
    /* @var $design Mage_Core_Model_Design_Package */
    $design = Mage::getSingleton('core/design_package');
    $layoutXml = null;
    $elementClass = $this->getElementClass();
    $updatesRoot = Mage::app()->getConfig()->getNode($area.'/layout/updates');
    Mage::dispatchEvent('core_layout_update_updates_get_after', array('updates' => $updatesRoot));
    $updateFiles = array();
    foreach ($updatesRoot->children() as $updateNode) {
        if ($updateNode->file) {
            $module = $updateNode->getAttribute('module');
            if ($module && Mage::getStoreConfigFlag('advanced/modules_disable_output/' . $module, $storeId)) {
                continue;
            }
            $updateFiles[] = (string)$updateNode->file;
        }
    }
    // custom local layout updates file - load always last
    $updateFiles[] = 'local.xml';
    $layoutStr = '';
    foreach ($updateFiles as $file) {
        $filename = $design->getLayoutFilename($file, array(
            '_area'    => $area,
            '_package' => $package,
            '_theme'   => $theme
        ));
        if (!is_readable($filename)) {
            continue;
        }
        $fileStr = file_get_contents($filename);
        $fileStr = str_replace($this->_subst['from'], $this->_subst['to'], $fileStr);   


        libxml_use_internal_errors(true);
        $fileXml = simplexml_load_string($fileStr, $elementClass);


        if (false === $fileXml) {
            // Put breakpoint here
            $errors = libxml_get_errors();
            $err = array($filename, $errors);
            // error detail and file name will be printed
            Zend_Debug::dump($err);
            die();
        }



        if (!$fileXml instanceof SimpleXMLElement) {
            continue;
        }
        $layoutStr .= $fileXml->innerXml();
    }
    $layoutXml = simplexml_load_string('<layouts>'.$layoutStr.'</layouts>', $elementClass);
    return $layoutXml;
}

Now just reload the page a read the error info.

like image 63
Roman Snitko Avatar answered Sep 30 '22 06:09

Roman Snitko


Well, after a good search, if the $string is all the CML merged, you have almost not chance to find what tag is bad closed.

I found a way to do it, in the class /lib/Varien/Simplexml/Config.php you have to modify the next method:

public function loadFile($filePath)
{
    if (!is_readable($filePath)) {
        //throw new Exception('Can not read xml file '.$filePath);
        return false;
    }

    $fileData = file_get_contents($filePath);
    $fileData = $this->processFileData($fileData);
    //add this try catch
    try{
        $this->loadString($fileData, $this->_elementClass);
    } catch (Exception $e) {
        var_dump("The error: " . $e->getMessage());
        var_dump("The bad file" . $filePath);
    }

    return $this->loadString($fileData, $this->_elementClass);
}

In this way we now can see what file has a bad tag.

like image 35
Beto Castillo Avatar answered Sep 30 '22 04:09

Beto Castillo