【问题标题】:XMLWriter error when creating XML file using PHP使用 PHP 创建 XML 文件时出现 XMLWriter 错误
【发布时间】:2013-01-29 22:24:42
【问题描述】:

执行下面的代码(减去数据库调用)后,我收到“第 7 列第 331 行错误:文档末尾的额外内容”错误。我浏览了这些论坛,但找不到解决方案。我没有任何随机字符或任何应该添加额外空格的代码......有什么想法吗?

<?php 
header('Content-type: text/xml');
mysql_connect("localhost", "---", "---");
mysql_select_db("---");

$query = "SELECT title FROM table";
$result = mysql_query($query);

$xml = new XMLWriter();
$xml->openURI("php://output");
$xml->startDocument();
$xml->setIndent(true);
$xml->writeRaw('<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9">');
$xml->startElement('url');
while ($row = mysql_fetch_assoc($result)) {
    if(!empty($row)){
        $title = $row['title'];
        $xml->startElement('loc');
            $xml->writeRaw('http://domain.com/article/');
        $xml->endElement();
        $xml->startElement('news:news');
            $xml->startElement("news:publication");
                $xml->startElement("news:name");
                    $xml->writeRaw('Name');
                $xml->endElement();
                $xml->startElement("news:language");
                    $xml->writeRaw('en');
                $xml->endElement();
            $xml->endElement();
            $xml->startElement('news:title');
                $xml->writeRaw($title);
            $xml->endElement();
            $xml->endElement();
    }
}
$xml->endElement();
$xml->flush();

【问题讨论】:

    标签: php xml xml-parsing whitespace xmlwriter


    【解决方案1】:

    编程中的一个关键点是降低某些代码的复杂性。这包括减少缩进,这样就不会有太多的代码相互粘连。这通常很难理解。

    例如,while 体内的 if 子句可以大大缩减,将内部已经向上移动一级:

    while ($row = mysql_fetch_assoc($result)) {
    
        if (empty($row)) {
            continue;
        }
    
        $title = $row['title'];
        ...
    }
    

    循环内的continue 只是说:下一次迭代。

    您创建的 XML 标记也有缩进。并非所有都可以预防,但是,有些可以。例如,XMLWriter::writeElement() 方法允许输出包含其内部文本的整个元素。这允许减少以下三行:

    $xml->startElement('loc');
        $xml->writeRaw('http://domain.com/article/');
    $xml->endElement();
    

    单人:

    $xml->writeElement('loc', 'http://domain.com/article/');
    

    由于有多组这样的行,现在的代码实际上已经很短了。通过结束文档也可以改善结尾,甚至不需要刷新。为了使缩进更易读,还可以使用方括号来表示缩进:

    while ($row = mysql_fetch_assoc($result)) {
    
        if (empty($row)) {
            continue;
        }
    
        $title = $row['title'];
    
        $xml->writeElement('loc', 'http://domain.com/article/');
    
        $xml->startElement('news:news');
        {
            $xml->startElement("news:publication");
            {
                $xml->writeElement("news:name", 'Name');
                $xml->writeElement("news:language", 'en');
            }
            $xml->endElement();
    
            $xml->writeElement('news:title', $title);
        }
        $xml->endElement();
    }
    
    $xml->endDocument();
    

    所以这不仅更具可读性,而且好消息是您确实遇到错误的情况也得到了修复。那是因为 XMLWriter::writeRaw() 方法已被删除。它写原始文本的功能是什么,这意味着未转义:

    $title = 'hackers <3 noodles';
    
    $xml->startElement('news:title');
        $xml->writeRaw($title);
    $xml->endElement();
    

    输出:

    <news:title>hackers <3 noodles</news:title>
                        ^
    

    正如输出所示,&lt; 字符逐字进入输出。根据标题,甚至可以注入纯 XML 代码,从而破坏整个文档结构并导致错误。使用XMLWriter::writeElement() 对此免疫:

    $title = 'hackers <3 noodles';
    
    $xml->writeElement('news:title', $title);
    

    输出:

    <news:title>hackers &lt;3 noodles</news:title>
                        ^^^^
    

    如输出所示,此处使用了属性 XML 实体来保留文档结构。

    所以你最初寻找的方法是XMLWriter::text()。但是对于这种情况,您不再需要它,因为优化后的代码不再存在该问题。所有文本输出都通过XMLReader::writeElement() 正确编码。另请参阅Retain XML code when using PHP XMLWriter::writeElement,这是关于同一主题但相反的主题。

    我希望这对你仍然有用,因为问题有点老了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多