2014-10-09 2 views
3

Я пытаюсь сделать веб-службу в PHP для приложения, с которым можно связаться, и получит данные из базы данных и поместит их в формат XML для приложения. Однако один из столбцов содержит HTML и должен быть выведен (я думаю) как CDATA. У меня проблемы с этим. Просьба сообщитьВывод переменных данных в формате CDATA XML с XMLWriter

<?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

'$ XML -> $ writeRaw' - второй "'$'", скорее всего, по ошибке? – hakre

+0

Я должен быть честным с тобой, изначально я пытался использовать кодировку JSON с прошлого четверга, и у меня было жестокое время, создавая его, а затем снова пытаясь разобрать его. Я чувствую себя более комфортно с XML, поэтому я просто вернулся к нему, пока не смогу понять NSJSONSerializer и написать код, чтобы сделать JSON без предупреждения. – Kirkland

ответ

4

Не используйте XMLWriter::writeRaw(), за исключением того, что если вы действительно хотите, чтобы писать фрагменты XML непосредственно. «Сырье» означает, что здесь не будет выхода из библиотеки.

Правильный способ записи текста в документ 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> 
+0

Большое спасибо за ваш ответ! Я добавил ваши изменения, и, к сожалению, я получаю сообщение об ошибке, когда он добирается до $ xml-> text ($ row = ['post_title']); Новый код этого сегмента: $ xml-> startElement ("PostTitle"); $ xml -> $ text ($ row ['post_title']); $ xml-> endElement(); Он отлично печатает дату с использованием того же кода, поэтому я не уверен, что здесь не так. Не могли бы вы помочь мне с этим последним? – Kirkland

+0

Хорошо, я скопировал и вставил рабочий сегмент, и теперь он работает, но только иногда. По какой-то причине он запускается, заполняется и заканчивается частью элемента post_title. Этот столбец в запросе всегда заполнен, поэтому я до сих пор не знаю, что с ним происходит. – Kirkland

+1

'$ xml -> $ text ($ row ['post_title']);' '' '' много. Он должен быть '$ xml-> text ($ row ['post_title']);' – ThW

0

Вы можете просто добавить его к элементам вам нужно завернутые с CDATA, как это:

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

Это может привести к недопустимому XML - '&' например, все еще нужно экранировать в разделах CDATA. – ThW

+0

Зачем вам нужно точно избегать символа &? Если я тестирую этот код, не ускользая от него, он все равно работает. –

+1

Ну, в случае '$ row ['post_date_gmt']' (который может не так, но может и это точка, поскольку он мог бы представлять любые данные переменной) содержит «']]> '» где-то там, это просто просто нарушено. Кроме того, это не очень умно: использование ** XMLWriter ** и предполагая, что проблема не была решена, уже сделала бы с использованием ** XMLWriter ** излишним. Это также является некоторой деградацией для ОП, задающей вопрос. Правильный ответ был бы следующим: '$ xml-> writeCData ($ row ['post_date_gmt']);' - потому что он уже завершает его. Не нужно заново изобретать колесо. – hakre

0

answer by ThW В целом задумчивый и путь. Он хорошо объясняет, как должен использоваться интерфейс XMLWriter в PHP.

Кредиты идут к нему также за большую часть работы, проделанной для этого дифференцированного ответа, когда мы обсуждали вопрос вчера в чате.

Есть некоторые Сдерживает с CDATA в XML, однако, что также относится и к намеченным двумя способами использования XMLWriter для CDATA:

Строка «]]>» не может быть помещен в секцию CDATA, поэтому вложенные секции CDATA не допускаются (ограничение корректности).

От: CDATA Section - сравните 2.7 CDATA Sections

Обычно XMLWriter принимает строковые данные, не закодированные для использования. Например. если вы передадите какой-либо текст, он будет правильно написан в закодированном виде (если только не указано XMLWriter::writeRaw).

Но если вы запустите секцию CDATA, а затем напишите текст или, вы пишете CDATA напрямую, переданная строка не должна заканчиваться и не содержать другого раздела CDATA. Это означает, что он не может содержать последовательность символов «]]>», так как это закончит раздел CDATA преждевременно.

Таким образом, ответственность за передачу достоверных данных в XMLWriter остается для пользователей этих методов.

Это, как правило, тривиально сделать так (однократный октета, набор US-ASCII основе символов двоичного кодирования и UTF-8), вот несколько примеров кода:

/** 
* 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 кстати. это что-то очень похожее под капотом уже:

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

Чтобы технически понять, почему XMLWriter в PHP ведет себя таким образом, вы должны знать, что XMLWriter основывается на libxml2 library. Расширение в PHP для большинства проделанной работы проходит звонки до Libxml: xmlwriter_write_cdata делегатов

PHP для Libxml xmlTextWriterWriteCDATA который делает suspected sequence из xmlTextWriterStartCDATA, xmlTextWriterWriteString и xmlTextWriterEndCDATA.

xmlTextWriterWriteString используется во многих процедур (например, записи PI), но только для некоторых случаев текста письма строка параметра содержание является кодируются:

  • Имя,
  • Текст и
  • Атрибут.

Для всех остальных это передается как есть.Это включает в себя CDATA, так что данные, передаваемые в XMLWriter::writeCData должны соответствовать требованиям, предъявляемым к XML CDATA (потому что написано этим методом):

  • [20] CData ::= (Char* - (Char* ']]>' Char*))

Который технически говоря: Любая строка не содержащий «]]>».

Это может быть легко пропущено, я сам подозревал, что это может быть ошибкой вчера. И я не единственный, связанный с этим отчет об ошибке на PHP.net: https://bugs.php.net/bug.php?id=44619 от лет назад.

Смотрите так же What does <![CDATA[]]> in XML mean?

Смежные вопросы