我正在尝试使用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();
?>
非常感谢您提供的任何帮助!
答案 0 :(得分:5)
除非您确实想直接编写XML片段,否则不要使用XMLWriter::writeRaw()
。 “原始”意味着这里不会逃离图书馆。
将文本写入XML文档的正确方法是XMLWriter::text()
。
$xml->startElement('PostTitle');
$xml->text('foo & bar');
$xml->endElement();
输出:
<?xml version="1.0"?>
<PostTitle>foo & 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
xmlTextWriterEndCDATA
,suspected sequence和xmlTextWriterWriteString
。
CData ::= (Char* - (Char* ']]>' Char*))
用于许多例程(例如编写PI),但仅针对某些文本编写案例,内容参数字符串 编码:
对于所有其他人,它按原样传递。这包括CDATA,因此传递给xmlTextWriterWriteString
的数据必须符合XML CData的要求(因为这是由该方法编写的):
]]>
技术上说:任何不包含“{{1}}”的字符串。
这很容易被忽视,我自己怀疑这可能是昨天的一个错误。而且我不是唯一一个,PHP.net上的相关错误报告是:XMLWriter::writeCData
来自多年前。