使用XMLWriter将变量数据输出为CDATA XML

时间:2014-10-09 10:26:26

标签: php sql xml cdata

我正在尝试使用PHP创建一个Web服务,以便与应用程序进行通信,从数据库获取数据并将其放入应用程序的XML格式。但是,其中一列包含HTML,需要输出(我认为)作为CDATA。虽然我很难完成这个。请指教

<?php
mysql_connect(DB_HOST, DB_USER, DB_PASSWORD);
mysql_select_db(DB_NAME);

$sql = "SELECT post_date_gmt, post_content, post_title FROM [schema].wp_posts WHERE post_status = \"publish\" && post_type = \"post\" ORDER BY post_date_gmt DESC;";
$res = mysql_query($sql);

$xml = new XMLWriter();

$xml->openURI("php://output");
$xml->startDocument();
$xml->setIndent(true);

$xml->startElement('BlogPosts');

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

    $xml->startElement("Post");

    $xml->startElement("PostDate");
    $xml->writeRaw($row['post_date_gmt']);
    $xml->endElement();

    $xml->startElement("PostTitle");
    $xml->$writeRaw($row['post_title']);
    $xml->endElement();

    $xml->startCData("PostContent");
    $xml->writeCData($row['post_content']);
    $xml->endCData();

    $xml->endElement();

}

$xml->endElement();

header('Content-type: text/xml');
$xml->flush();

?>

非常感谢您提供的任何帮助!

3 个答案:

答案 0 :(得分:5)

除非您确实想直接编写XML片段,否则不要使用XMLWriter::writeRaw()。 “原始”意味着这里不会逃离图书馆。

将文本写入XML文档的正确方法是XMLWriter::text()

$xml->startElement('PostTitle');
$xml->text('foo & bar');
$xml->endElement();

输出:

<?xml version="1.0"?>
<PostTitle>foo &amp; bar</PostTitle>

如果您在此示例中使用XMLWriter::writeRaw(),则结果将包含未转义的&且无效的XML。

CDATA部分是与文本节点不同的字符节点,但允许特殊字符而不转义并保留空格。您始终必须单独创建元素节点。元素节点可以包含多个其他节点,甚至包含多个CDATA节。

XmlReader有两种创建CDATA部分的方法:

单一方法:

$xml->startElement("PostContent");
$xml->writeCData('<b>post</b> content');
$xml->endElement();

输出:

<?xml version="1.0"?>
<PostContent><![CDATA[<b>post</b> content]]></PostContent>

或开始/结束方法:

$xml->startElement("PostContent");
$xml->startCData();
$xml->text('<b>post</b> content');
$xml->text(' more content');
$xml->endCData();
$xml->endElement();

输出:

<?xml version="1.0"?>
<PostContent><![CDATA[<b>post</b> content more content]]></PostContent>

答案 1 :(得分:0)

您可以将它添加到需要用CDATA包装的元素中,如下所示:

 $xml->writeRaw('<![CDATA['.$row['post_date_gmt'].']]>');

答案 2 :(得分:0)

answer by ThW总体上是深思熟虑的,也是要走的路。它很好地解释了如何使用PHP中XMLWriter的接口。

在我们昨天在聊天中讨论过这个问题的过程中,还有大量的工作要归功于这个差异化的答案。

XML中存在一些CDATA约束,但这也适用于为CDATA使用 XMLWriter 概述的两种方式:

  

字符串']]&gt;'不能放在CDATA部分内,因此,不允许嵌套的CDATA部分(良构性约束)。

来自:CDATA Section - 比较2.7 CDATA Sections

通常 XMLWriter 接受未编码的字符串数据。例如。如果您传递一些文本,它将被正确编码(除非是直言XMLWriter::writeRaw)。

但是如果您启动CDATA部分然后写入文本直接写CDATA,则传递的字符串不得结束,也不能包含另一个CDATA部分。这意味着,它不能包含字符序列“]]>”,因为这会过早地结束CDATA部分。

因此,将有效数据传递给XMLWriter的责任仍然是这些方法的用户。

这样做通常很简单(单八位字节,基于US-ASCII的字符集二进制编码和UTF-8 Unicode),这里有一些示例代码:

/**
 * prepare text for CDATA section to prevent invalid or nested CDATA
 *
 * @param $string
 *
 * @return string
 * @link http://www.w3.org/TR/REC-xml/#sec-cdata-sect
 */
function xmlwriter_prepare_cdata_text($string) {
    return str_replace(']]>', ']]]]><![CDATA[>', (string) $string);
}

一个用法示例:

$xml = new XMLWriter();
$xml->openURI("php://output");
$xml->startDocument();

$xml->startElement("PostContent");
$xml->writeCDATA(xmlwriter_prepare_cdata_text('<![CDATA[Foo & Bar]]>'));
$xml->endElement();

$xml->endElement();

示例性输出:

<?xml version="1.0"?>
<PostContent><![CDATA[<![CDATA[Foo & Bar]]]]><![CDATA[>]]></PostContent>

DOMDocument btw。已经做了类似的事情:

$dom = new DOMDocument();
$dom->appendChild(
    $dom->createElement('PostContent')
);
$dom->documentElement->appendChild(
    $dom->createCdataSection('<![CDATA[Foo & Bar]]>')
);
$dom->save("php://output");

输出:

<?xml version="1.0"?>
<PostContent><![CDATA[<![CDATA[Foo & Bar]]]]><![CDATA[>]]></PostContent>

要从技术上理解为什么PHP中的 XMLWriter 以这种方式运行,您需要知道 XMLWriter 基于libxml2 library。 PHP完成大部分工作的扩展将调用传递给libxml:

PHP xmlwriter_write_cdata委托给libxml xmlTextWriterWriteCDATA代理xmlTextWriterStartCDATA xmlTextWriterEndCDATAsuspected sequencexmlTextWriterWriteString

CData ::= (Char* - (Char* ']]>' Char*))用于许多例程(例如编写PI),但仅针对某些文本编写案例,内容参数字符串 编码:

  • 姓名,
  • 文字和
  • 属性。

对于所有其他人,它按原样传递。这包括CDATA,因此传递给xmlTextWriterWriteString的数据必须符合XML CData的要求(因为这是由该方法编写的):

  • [20] ]]>

技术上说:任何不包含“{{1}}”的字符串。

这很容易被忽视,我自己怀疑这可能是昨天的一个错误。而且我不是唯一一个,PHP.net上的相关错误报告是:XMLWriter::writeCData来自多年前。

另见https://bugs.php.net/bug.php?id=44619