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?
'$ XML -> $ writeRaw' - второй "'$'", скорее всего, по ошибке? – hakre
Я должен быть честным с тобой, изначально я пытался использовать кодировку JSON с прошлого четверга, и у меня было жестокое время, создавая его, а затем снова пытаясь разобрать его. Я чувствую себя более комфортно с XML, поэтому я просто вернулся к нему, пока не смогу понять NSJSONSerializer и написать код, чтобы сделать JSON без предупреждения. – Kirkland