用PHP生成XML文檔(轉義字符)
我正在從PHP腳本生成XML文檔,并且需要轉義XML特殊字符。我知道應該轉義的字符列表; 但是正確的方法是什么?
應該使用反斜杠(\')來轉義字符還是正確的方法?有內置的PHP函數可以為我處理此問題嗎?
Tomas Jancik asked 2020-06-22T22:40:59Z
10個解決方案
36 votes
我創建了一個簡單的函數,該函數使用XML中的五個“預定義實體”進行轉義:
function xml_entities($string) {
return strtr(
$string,
array(
" "<",
">" => ">",
'"' => """,
"'" => "'",
"&" => "&",
)
);
}
用法示例演示:
$text = "Test & and encode :)";
echo xml_entities($text);
輸出:
Test & <b> and encode </b> :)
通過使用str_replace可以達到類似的效果,但是由于兩次替換(未試用,不建議使用),它很脆弱:
function xml_entities($string) {
return str_replace(
array("&", "", '"', "'"),
array("&", "<", ">", """, "'"),
$string
);
}
Tomas Jancik answered 2020-06-22T22:42:07Z
34 votes
使用DOM類生成整個XML文檔。 它將處理我們甚至不需要關心的編碼和解碼。
編輯:這被@Tchalvak批評:
DOM對象創建了一個完整的XML文檔,它不容易將其自身編碼為一個字符串。
錯了,DOMDocument只能輸出一個片段而不是整個文檔:
$doc->saveXML($fragment);
這使:
Test & and encode :)
Test & <b> and encode </b> :)
如:
$doc = new DOMDocument();
$fragment = $doc->createDocumentFragment();
// adding XML verbatim:
$xml = "Test & and encode :)\n";
$fragment->appendXML($xml);
// adding text:
$text = $xml;
$fragment->appendChild($doc->createTextNode($text));
// output the result
echo $doc->saveXML($fragment);
觀看演示
Ionu? G. Stan answered 2020-06-22T22:41:33Z
17 votes
那get_html_translation_table()函數呢?
htmlspecialchars($input, ENT_QUOTES | ENT_XML1, $encoding);
注意:僅當您具有PHP 5.4.0或更高版本時,get_html_translation_table()標志才可用。
使用這些參數的get_html_translation_table()替換了以下字符:
get_html_translation_table()(與號)變成>
get_html_translation_table()(雙引號)變成>
get_html_translation_table()(單引號)變為>
get_html_translation_table()(小于)變成>
get_html_translation_table()(大于)變為>
您可以使用get_html_translation_table()函數獲取翻譯表。
MarcDefiant answered 2020-06-22T22:43:02Z
13 votes
嘗試解決XML實體問題,以這種方式解決:
htmlspecialchars($value, ENT_QUOTES, 'UTF-8')
Josh Sunderman answered 2020-06-22T22:43:22Z
5 votes
為了擁有有效的最終XML文本,您需要轉義所有XML實體,并以與XML文檔處理指令所聲明的格式相同的編碼來編寫文本(<?xml行中的 “編碼”)。 只要將重音字符編碼為文檔,就不必對其進行轉義。
但是,在許多情況下,僅用iconv()轉義輸入可能會導致對實體進行雙重編碼(例如utf8_encode()將變為é),因此我建議先對html實體進行解碼:
function xml_escape($s)
{
$s = html_entity_decode($s, ENT_QUOTES, 'UTF-8');
$s = htmlspecialchars($s, ENT_QUOTES, 'UTF-8', false);
return $s;
}
現在,您需要確保所有重音字符在XML文檔編碼中均有效。 我強烈建議始終以UTF-8編碼XML輸出,因為并非所有XML解析器都遵循XML文檔處理指令編碼。 如果您的輸入可能來自其他字符集,請嘗試使用iconv()。
有一種特殊情況,即您的輸入可能來自以下一種編碼:ISO-8859-1,ISO-8859-15,UTF-8,cp866,cp1251,cp1252和KOI8-R-PHP會將它們全部 相同,但是它們之間存在一些細微差異-甚至iconv()也無法處理其中的某些差異。 我只能通過補充utf8_encode()行為來解決此編碼問題:
function encode_utf8($s)
{
$cp1252_map = array(
"\xc2\x80" => "\xe2\x82\xac",
"\xc2\x82" => "\xe2\x80\x9a",
"\xc2\x83" => "\xc6\x92",
"\xc2\x84" => "\xe2\x80\x9e",
"\xc2\x85" => "\xe2\x80\xa6",
"\xc2\x86" => "\xe2\x80\xa0",
"\xc2\x87" => "\xe2\x80\xa1",
"\xc2\x88" => "\xcb\x86",
"\xc2\x89" => "\xe2\x80\xb0",
"\xc2\x8a" => "\xc5\xa0",
"\xc2\x8b" => "\xe2\x80\xb9",
"\xc2\x8c" => "\xc5\x92",
"\xc2\x8e" => "\xc5\xbd",
"\xc2\x91" => "\xe2\x80\x98",
"\xc2\x92" => "\xe2\x80\x99",
"\xc2\x93" => "\xe2\x80\x9c",
"\xc2\x94" => "\xe2\x80\x9d",
"\xc2\x95" => "\xe2\x80\xa2",
"\xc2\x96" => "\xe2\x80\x93",
"\xc2\x97" => "\xe2\x80\x94",
"\xc2\x98" => "\xcb\x9c",
"\xc2\x99" => "\xe2\x84\xa2",
"\xc2\x9a" => "\xc5\xa1",
"\xc2\x9b" => "\xe2\x80\xba",
"\xc2\x9c" => "\xc5\x93",
"\xc2\x9e" => "\xc5\xbe",
"\xc2\x9f" => "\xc5\xb8"
);
$s=strtr(utf8_encode($s), $cp1252_map);
return $s;
}
Capilé answered 2020-06-22T22:43:56Z
2 votes
如果您需要正確的xml輸出,則可以使用simplexml:
[HTTP://嗚嗚嗚.PHP.net/manual/恩/simple XML element.as XML.PHP]
nubeiro answered 2020-06-22T22:44:21Z
1 votes
正確的轉義是獲得正確的XML輸出的方法,但是您需要對屬性和元素進行不同的轉義處理。 (那是Tomas的回答是不正確的)。
我寫/偷了一些Java代碼,以區分屬性和元素轉義。 原因是XML解析器認為所有空白特別是屬性中的空白。
將其移植到PHP上應該很簡單(您可以使用Tomas Jancik的方法進行上述適當的轉義)。 如果您使用UTF-8,則不必擔心轉義擴展實體。
如果您不想移植我的Java代碼,可以查看XMLWriter,它基于流并且使用libxml,因此它應該非常有效。
Adam Gent answered 2020-06-22T22:44:55Z
0 votes
您可以使用以下方法:[http://php.net/manual/en/function.htmlentities.php]
這樣,所有實體(html / xml)均被轉義,您可以將字符串放入XML標簽內
Alois Cochard answered 2020-06-22T22:45:19Z
-1 votes
基于sadeghj的解決方案,以下代碼為我工作:
/**
* @param $arr1 the single string that shall be masked
* @return the resulting string with the masked characters
*/
function replace_char($arr1)
{
if (strpos ($arr1,'&')!== FALSE) { //test if the character appears
$arr1=preg_replace('/&/','&', $arr1); // do this first
}
// just encode the
if (strpos ($arr1,'>')!== FALSE) {
$arr1=preg_replace('/>/','>', $arr1);
}
if (strpos ($arr1,'
$arr1=preg_replace('/','<', $arr1);
}
if (strpos ($arr1,'"')!== FALSE) {
$arr1=preg_replace('/"/','"', $arr1);
}
if (strpos ($arr1,'\'')!== FALSE) {
$arr1=preg_replace('/\'/',''', $arr1);
}
return $arr1;
}
paderEpiktet answered 2020-06-22T22:45:39Z
-2 votes
function replace_char($arr1)
{
$arr[]=preg_replace('>','>', $arr1);
$arr[]=preg_replace('
$arr[]=preg_replace('"','"', $arr1);
$arr[]=preg_replace('\'','&apos', $arr1);
$arr[]=preg_replace('&','&', $arr1);
return $arr;
}
sadeghj answered 2020-06-22T22:45:54Z