使用PHP创建XML文件时出现XMLWriter错误

时间:2013-01-29 22:24:42

标签: php xml xml-parsing whitespace xmlwriter

执行下面的代码(减去数据库调用)后,我收到“第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();

1 个答案:

答案 0 :(得分:3)

编程的一个关键点是降低某些代码的复杂性。这包括减少缩进,以便没有太多的代码插入彼此。这通常很难理解。

例如,while body中的if子句可以大大减少,内部已经向上移动了一个级别:

while ($row = mysql_fetch_assoc($result)) {

    if (empty($row)) {
        continue;
    }

    $title = $row['title'];
    ...
}

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

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

$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>
                    ^

如输出所示,<字符逐字输入输出。根据标题,甚至可以注入纯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,它是关于同一主题但来自相反的主题。

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