如何处理以HTML/php形式输出到XML的所有特殊字符


how to handle all special characters in HTML/php form that outputs to XML

我有一个小的php/mysql应用程序,我把它放在一起,输入表单并将其存储在mysql数据库中,并输出数据作为XML供广播播放硬件设备使用。

问题在于&和其他字符。用户正在获取各种广播电台的描述,以及流媒体URL或播放列表URL,并将它们粘贴到表单中。有些广播电台设在非英语国家(主要是法语国家)。我需要知道如何预处理这些字段,以便生成的XML不会损坏,这会破坏外部硬件应用程序。

我假设这应该在提交表单时被调用的php中。我很确定应该使用htmlspecialchars函数,但我不确定最好的方法,因为我已经从各种来源将其hack在一起:

UPDATE:这是我当前的输出代码,带有一些清除&号的正则表达式。

<?
include("HLN/manager/connect.php");
$query = "SELECT * FROM hln_stations ORDER BY orderid ASC";
$result = mysql_query($query);
$num = mysql_num_rows ($result);
mysql_close();
$xml = new XMLWriter();
$xml->openURI("php://output");
$xml->startDocument();
header('Content-type: text/xml');
$xml->setIndent(true);
$xml->startElement('channels');
while ($row = mysql_fetch_assoc($result)) {
  $xml->startElement("channel");
     $xml->startElement("title");
          $xml->writeRaw(preg_replace('/&(?![A-Za-z0-9#]{1,7};)/','&amp;',$row['station_title']));
     $xml->endElement();
     $xml->startElement("descriptionline1");
          $xml->writeRaw(preg_replace('/&(?![A-Za-z0-9#]{1,7};)/','&amp;',$row['station_display_name']));
     $xml->endElement();
     $xml->startElement("descriptionline2");
          $xml->writeRaw(preg_replace('/&(?![A-Za-z0-9#]{1,7};)/','&amp;',$row['station_subtitle']));
     $xml->endElement();
     $xml->startElement("description");
          $xml->writeRaw(preg_replace('/&(?![A-Za-z0-9#]{1,7};)/','&amp;',$row['station_detailed_description']));
     $xml->endElement();
     $xml->startElement("sdimage");
          $xml->writeRaw(preg_replace('/&(?![A-Za-z0-9#]{1,7};)/','&amp;',$row['sdtv_thumbnail_graphic_url']));
     $xml->endElement();
     $xml->startElement("hdimage");
          $xml->writeRaw(preg_replace('/&(?![A-Za-z0-9#]{1,7};)/','&amp;',$row['hdtv_thumbnail_graphic_url']));
     $xml->endElement();
     $xml->startElement("uri");
          $xml->writeRaw(preg_replace('/&(?![A-Za-z0-9#]{1,7};)/','&amp;',$row['stream_url_or_playlist_url']));
     $xml->endElement();
     $xml->startElement("linktype");
          $xml->writeRaw(preg_replace('/&(?![A-Za-z0-9#]{1,7};)/','&amp;',$row['link_type']));
     $xml->endElement();
 $xml->endElement();
}
$xml->endElement();

$xml->flush();
?>

但是我仍然需要解决突然出现的法语字符集问题。例如,我如何用不会引起问题的东西来替换字符?

您在Firefox中出现了一个错误,表示格式不佳,因为检测到的字符集与您输出的字符集不匹配。我尝试了不同的字符集组合,还是出现了同样的问题。

您必须明确指定您的字符集,例如:

header('Content-type: text/xml; charset=UTF-8');
$xml = new XMLWriter();
$xml->openURI("php://output");
$xml->startDocument("1.0", "UTF-8");

如果在内容类型和XML中指定字符集为UTF-8会给您错误,这意味着您的输入不是有效的UTF-8,请尝试使用ISO-8859-15代替,或重新编码您的输入。

您必须为站点的每个页面(包括用于输入数据的表单)放置内容类型的字符集头,否则您的特殊字符可能会混乱。此外,你必须连接到mysql指定的字符集,你想要使用的连接,应该匹配的字符集和排序表。

假设你使用的是UTF-8,看看PHPMyAdmin和UTF-8连接的数据库,如果你不能看到你的特殊字符,这意味着你做错了。

对于设备,如果你说它只能显示ASCII字符,当你输入UTF-8时,它会为你做转换吗?还是你必须给实体,如:

Ch&#xE9;rie 

如果这两个选项不起作用,您可能需要转换为ASCII,例如"Cherie"…但那将是最后的选择。


不使用DB的概念验证代码:

<?php
header('Content-type: text/xml; charset=UTF-8');
$radioArr = array(
   array("Chérie FM @Work", "http://www.listenlive.eu/cheriefm_atwork.m3u?p&test"), 
   array("Hélène FM", "http://broadcast.infomaniak.ch/helenefm-high.mp3.m3u")
);
$xml = new XMLWriter();
$xml->openURI("php://output");
$xml->startDocument("1.0", "UTF-8");
$xml->setIndent(true);
$xml->startElement('channels');
foreach ($radioArr AS $radio) {
     $xml->startElement("channel");
     $xml->startElement("title");
     $xml->writeRaw(preg_replace('/&(?![A-Za-z0-9#]{1,7};)/','&amp;', $radio[0]));
     $xml->endElement();
     $xml->startElement("uri");
     $xml->writeRaw(preg_replace('/&(?![A-Za-z0-9#]{1,7};)/','&amp;', $radio[1]));
     $xml->endElement();
     $xml->endElement(); //end channel
}
$xml->endElement();
$xml->flush();
?>

如果你真的想"清除法语字符" (remove)

这样做(iconv)怎么样?

iconv('utf8', 'ascii//TRANSLIT', $text);

使用CDATA包装数据。用writeCData()代替writeRaw()请参考下面的示例。

// CData output
$xml->startElement('title');
$xml->writeCData($row['station_subtitle']);
$xml->endElement();