【问题标题】:How to easily Debug Layout Xml Warning/Error?如何轻松调试布局 Xml 警告/错误?
【发布时间】:2012-10-31 06:14:32
【问题描述】:

我遇到了这个错误:

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

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

很明显,有些Xml文件有问题,但是大海捞针对我来说真的不容易:)

有什么好的做法吗? 如果可能的话,我想找到一个涉及使用 Xdebug 或一些日志的好习惯。

在 Magento 中经常发生拼写错误。

【问题讨论】:

    标签: xml debugging magento xdebug


    【解决方案1】:

    我想你可以看看这篇文章Dealing with XML errors

    此警告与某些 config.xml 错误有关,因此找出确切文件的可能解决方法是修改。 /lib/Varien/Simplexml/Config.php 类。

    你应该修改Varien_Simplexml_Config::loadString()方法:

    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;
    }
    

    如果错误与某些 Layout 文件有关(Update.php 第 444 行警告)

    你应该以类似的方式修改Mage_Core_Model_Layout_Update::getFileLayoutUpdatesXml()方法:

    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;
    }
    

    现在只需重新加载页面并阅读错误信息。

    【讨论】:

    • Magento 架构没有什么特别的,它只是 XML 文件 :)
    • 你知道magento中有多少个xml,每次加载页面时这行代码会触发多少次吗?
    • 我当然知道。但是这些方法将只考虑带有错误的 xml 字符串。只有当 xml 字符串加载出现问题时,您才应该调用 libxml_get_errors()
    • 好的,你能添加精确的指令吗?我应该在哪里添加一些代码?
    • 谢谢,这是解决方案的一部分,我可以知道模块名称,但不能知道当前处理的文件
    【解决方案2】:

    好吧,经过好好搜索,如果$string是所有的CML合并的,你几乎没有机会找到什么标签是坏关闭的。

    我找到了一种方法,在 /lib/Varien/Simplexml/Config.php 类中你必须修改下一个方法:

    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);
    }
    

    通过这种方式,我们现在可以看到哪个文件有错误的标签。

    【讨论】:

      【解决方案3】:

      如果您的测试环境是 Linux,您还可以使用 XMLLint xmllint 在对布局 xml 文件进行更改后检查它是否存在不一致。在实施之前进行检查可以发现许多错误并防止引发错误。

      【讨论】:

      • 我已经试过好几次了。它在修复 Magento 中的 XML 问题方面非常有效。这是您将在终端 for file in find 中使用的命令。 -name "*.xml"; do xmllint --noout $file; done
      【解决方案4】:

      编辑文件 app/code/core/Mage/Core/Model/Layout/Update.php 并搜索函数“getFileLayoutUpdatesXml”。

      添加:

      Mage::log(print_r($filename, true));
      

      大约在第 442 行,之前:

      $fileStr = file_get_contents($filename);
      

      【讨论】:

        【解决方案5】:

        要解决这种情况,请在第 489 行的同一文件 */lib/Varien/Simplexml/Config.php 中

        加载的XML文件的打印路径放在Zend_Debug::dump($filePath);之后$fileData = $this-&gt;processFileData($fileData);

        并覆盖函数 loadString($string)


        if (is_string($string)) {
            $xml = simplexml_load_string($string, $this->_elementClass);
            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;
        

        替换为

        if (is_string($string)) {
            // Enable internal errors
            //Mage::log($string);
            libxml_use_internal_errors(true);
            $xml = simplexml_load_string($string, $this->_elementClass);
        
            if (false === $xml) {
                // Put breakpoint here
                $errors = libxml_get_errors();
                $err = array($errors);
                // error detail and file name will be printed
                Zend_Debug::dump($string);;
                Zend_Debug::dump($err);
                die();
            }
            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;
        

        这将打印出问题所在的路径和错误。

        【讨论】:

          【解决方案6】:

          */lib/Varien/Simplexml/Config.php on line 510
          

          去添加一个调试行并回显它尝试加载的xml,看看这个字符串有什么问题。

          【讨论】:

          • 你的解决方案是我一直使用的我可以说它不是很有效:问题是magento加载了很多xml,所以调试行会触发数千次......我有尝试添加try{} catch{} 但因为它是一个警告...
          猜你喜欢
          • 1970-01-01
          • 2019-06-09
          • 2012-01-14
          • 1970-01-01
          • 2013-03-25
          • 1970-01-01
          • 2011-12-24
          • 2011-10-09
          • 1970-01-01
          相关资源
          最近更新 更多