代码之家  ›  专栏  ›  技术社区  ›  JW.

dom错误-id“someanchor”已在实体的第x行中定义

  •  7
  • JW.  · 技术社区  · 16 年前

    如果我尝试将HTML文档加载到php dom中,会得到一个错误,其内容如下:

    Error DOMDocument::loadHTML() [domdocument.loadhtml]: ID someAnchor already defined in Entity, line: 9
    

    我不知道为什么。下面是一些将HTML字符串加载到DOM中的代码。

    第一个不包含锚标记,第二个包含锚标记。第二个文档产生错误。

    希望您能够将其剪切并粘贴到脚本中,然后运行它以查看相同的输出:

    <?php
    ini_set('display_errors', 1);
    error_reporting(E_ALL);
    
    
    $stringWithNoAnchor = <<<EOT
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <title>My document</title>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    </head>
    <body >
    <h1>Hello</h1>
    </body>
    </html>
    EOT;
    
    $stringWithAnchor = <<<EOT
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <title>My document</title>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    </head>
    <body >
    <h1>Hello</h1>
    <a name="someAnchor" id="someAnchor"></a>
    </body>
    </html>
    EOT;
    
    class domGrabber
        {
        public $_FileErrorStr = '';
    
        /**
        *@desc DOM object factory does the work of loading the DOM object
        */
        public function getLoadAsDOMObj($htmlString)
            {
            $this->_FileErrorStr =''; //reset error container
            $xmlDoc = new DOMDocument();
            set_error_handler(array($this, '_FileErrorHandler')); // Warnings and errors are suppressed
            $xmlDoc->loadHTML($htmlString);
            restore_error_handler();
            return $xmlDoc;
            }
    
        /**
        *@desc public so that it can catch errors from outside this class
        */
        public function _FileErrorHandler($errno, $errstr, $errfile, $errline)
            {
            if ($this->_FileErrorStr === null)
                {
                $this->_FileErrorStr = $errstr;
                }
            else    {
                $this->_FileErrorStr .= (PHP_EOL . $errstr);
                }
            }
        }
    
    $domGrabber = new  domGrabber();
    $xmlDoc = $domGrabber->getLoadAsDOMObj($stringWithNoAnchor );
    
    echo 'PHP Version: '. phpversion() .'<br />'."\n";
    
    echo '<pre>';
    print $xmlDoc->saveXML();
    echo '</pre>'."\n";
    if ($domGrabber->_FileErrorStr)
        {
        echo 'Error'. $domGrabber->_FileErrorStr;
        }
    
    
    
    $xmlDoc = $domGrabber->getLoadAsDOMObj($stringWithAnchor);
    echo '<pre>';
    print $xmlDoc->saveXML();
    echo '</pre>'."\n";
    if ($domGrabber->_FileErrorStr)
        {
        echo 'Error'. $domGrabber->_FileErrorStr;
        }
    

    在我的Firefox源代码视图中,我得到了以下信息:

    PHP Version: 5.2.9<br />
    <pre><?xml version="1.0" encoding="iso-8859-1" standalone="yes"?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/xhtml"><head><title>My document</title><meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /></head><body>
    <h1>Hello</h1>
    </body></html>
    </pre>
    <pre><?xml version="1.0" encoding="iso-8859-1" standalone="yes"?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/xhtml"><head><title>My document</title><meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /></head><body>
    <h1>Hello</h1>
    <a name="someAnchor" id="someAnchor"></a>
    
    </body></html>
    </pre>
    Error
    DOMDocument::loadHTML() [<a href='domdocument.loadhtml'>domdocument.loadhtml</a>]: ID someAnchor already defined in Entity, line: 9
    

    那么,为什么dom说已经定义了锚?


    更新:

    我两个都做过实验

    • 我没有使用loadHTML(),而是使用了loadXML()方法,并修复了它
    • 我没有同时使用id和name,只使用了id属性,并修复了它。

    为了完成,请参阅下面的比较脚本:

    <?php
    ini_set('display_errors', 1);
    error_reporting(E_ALL);
    
    
    $stringWithNoAnchor = <<<EOT
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <title>My document</title>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    </head>
    <body >
    <p>stringWithNoAnchor</p>
    </body>
    </html>
    EOT;
    
    $stringWithAnchor = <<<EOT
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <title>My document</title>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    </head>
    <body >
    <p>stringWithAnchor</p>
    <a  name="someAnchor" id="someAnchor" ></a>
    </body>
    </html>
    EOT;
    
    $stringWithAnchorButOnlyIdAtt = <<<EOT
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <title>My document</title>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    </head>
    <body >
    <p>stringWithAnchorButOnlyIdAtt</p>
    <a id="someAnchor"></a>
    </body>
    </html>
    EOT;
    
    class domGrabber
        {
        public $_FileErrorStr = '';
        public $useHTMLMethod = TRUE;
    
        /**
        *@desc DOM object factory does the work of loading the DOM object
        */
        public function loadDOMObjAndWriteOut($htmlString)
            {
            $this->_FileErrorStr ='';
    
            $xmlDoc = new DOMDocument();
            set_error_handler(array($this, '_FileErrorHandler')); // Warnings and errors are suppressed
    
    
            if ($this->useHTMLMethod)
                {
                $xmlDoc->loadHTML($htmlString);
                }
            else    {
                $xmlDoc->loadXML($htmlString);
                }
    
    
            restore_error_handler();
    
            echo "<h1>";
            echo ($this->useHTMLMethod) ? 'using xmlDoc->loadHTML() ' : 'using $xmlDoc->loadXML()';
            echo "</h1>";
            echo '<pre>';
            print $xmlDoc->saveXML();
            echo '</pre>'."\n";
            if ($this->_FileErrorStr)
                {
                echo 'Error'. $this->_FileErrorStr;
                }
            }
    
        /**
        *@desc public so that it can catch errors from outside this class
        */
        public function _FileErrorHandler($errno, $errstr, $errfile, $errline)
            {
            if ($this->_FileErrorStr === null)
                {
                $this->_FileErrorStr = $errstr;
                }
            else    {
                $this->_FileErrorStr .= (PHP_EOL . $errstr);
                }
            }
        }
    
    $domGrabber = new  domGrabber();
    
    echo 'PHP Version: '. phpversion() .'<br />'."\n";
    
    $domGrabber->useHTMLMethod = TRUE; //DOM->loadHTML
    $domGrabber->loadDOMObjAndWriteOut($stringWithNoAnchor);
    $domGrabber->loadDOMObjAndWriteOut($stringWithAnchor );
    $domGrabber->loadDOMObjAndWriteOut($stringWithAnchorButOnlyIdAtt);
    
    $domGrabber->useHTMLMethod = FALSE; //use DOM->loadXML
    $domGrabber->loadDOMObjAndWriteOut($stringWithNoAnchor);
    $domGrabber->loadDOMObjAndWriteOut($stringWithAnchor );
    $domGrabber->loadDOMObjAndWriteOut($stringWithAnchorButOnlyIdAtt);
    
    1 回复  |  直到 11 年前
        1
  •  9
  •   Artefacto    16 年前

    如果您正在加载XML文件(即XHTML是XML),那么应该使用 DOMDocument::loadXML() 不是 DOMDocument::loadHTML() .

    在HTML中,两者都 name id 引入一个ID。这样您就重复了ID“someanchor”,因此出现了错误。

    但是,W3C验证器允许在显示的表单中重复ID <a id="someAnchor" name="someAnchor"></a> . 这可能是libmxl2的错误。

    在这 bug report 对于libxml2,用户建议只考虑 名称 作为ID的属性:

    根据HTML和XHTML规范,只有a元素的name属性 与ID属性共享名称空间。对于某些因素,它是可以论证的。 同名的多个实例没有意义,但它们应该 不过,不能将其与其他元素的ID放在同一命名空间中。 属性。

    http://www.zvon.org/xxl/xhtmlReference/Output/Strict/attr_name.html 为了所有 采用名称属性及其语义的元素。

    推荐文章