使用PHP 5.3.13
解析xml时,simplexml_load_string 会抛出实体'除以'未定义错误。
此问题的大多数解决方案都集中在如何处理 SimpleXMLElement 及其 addChild 和 addAttribue 方法。这些方法将一些特殊字符转换为实体。然后解决方案似乎要处理 simplexml_load_string 不理解的几个特殊字符。
问题是列表非常大,如果你在$ string上使用 htmlentities($ string,ENT_QUOTES,'UTF-8',true),你将要插入XML addChild 然后它会添加正常但 simplexml_load_string 会在尝试从 SimpleXMLElement 生成的 as_xml 解析生成的XML时崩溃。
另一个问题是生成的实体列表可能很长,但用户可以轻松输入以下& pizza;它会打破解析器。由于我需要处理所有用户输入,我想出了以下内容,但想知道你是否看到它会失败。
想知道以下解决方案是否有效: 替换&带有& amp;的字符串中的任何地方。 我一直无法找到一个案例,因为我的解决方案已经解决,但因为它很简单,我还没有把它看作列出的解决方案
以下是我可能的解决方案的示例代码:
$content_amp_safe = str_replace('&','&',$content);
以下是错误消息:
警告:simplexml_load_string():实体:第11行:解析器错误:内部错误 实体“鸿沟”未定义
以下是导致问题解决前的代码:
<?php
// insert that causes the issue with the windows encoded dash, triple dot, and right quote as an example
// also issue if user enters &pizza; in the text as it is an unknown entity
$content = "I love &pizza; in the … morning's – night as well";
$content_unsafe = htmlentities($content, ENT_QUOTES, 'UTF-8', true);
//fix is to use $content_amp_safe string instead
$content_amp_safe = str_replace('&','&',$content_unsafe);
$xml = new SimpleXMLElement("<?xml version='1.0' encoding='utf-8'?><Entries />");
$entry = $xml->addChild('Entry');
$entry->addChild('Content', $content);
$xml_string = $xml->asXML();
libxml_use_internal_errors(true);
$xml = simplexml_load_string($xml_string);
if ($xml === false) {
$error_string = "Failed loading XML\n";
foreach ( libxml_get_errors() as $error ) {
$error_string .= "\t" . $error->message;
}
echo $error_string;
));
}
libxml_use_internal_errors(false);
?>
使用 htmlentities 对用户输入导致问题的某些字符的简短版本。
<?php
$table = get_html_translation_table(HTML_ENTITIES, ENT_QUOTES, 'cp1252');
var_dump($table);
?>
示例字符:
€,ƒ“...†‡‡<Œ''”“• - 〜™š>œŸ¢¢¥|§«ª«¬®¯°±³³μμ··· »¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ&安培;“'&LT;&GT;
示例编码:
€,ƒ“...†‡‰Š<Œ ''‘’•--~™S>œŸ¡¢£¤¥|§¨©ª«¬®¯°±²³'μ¶·¸¹º »¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ&安培;“'&LT;&GT;
示例新编码:
&安培;欧元;&安培; sbquo;&安培; fnof;&安培; bdquo;&安培; hellip;&安培;匕首;&安培;匕首;&安培; CIRC;&安培; permil;&安培; Scaron;&安培; lsaquo;上&安培; OElig ;&安培; lsquo的;&安培; rsquo的;&安培; ldquo;&安培; rdquo;的&安培;公牛;&安培; ndash的;&安培; MDASH;&安培;波浪;&安培;贸易;&安培; scaron;&安培; rsaquo;&安培; oelig;&放; Yuml;&安培; NBSP;&安培; iexcl;&安培;百分之;&安培;磅;&安培; CURREN;&安培;日元;&安培; brvbar;&安培;节;&安培; UML;&安培;复印;&安培; ordf;&安培; LAQUO ;&安培;不;&安培;害羞;&安培; REG;&安培; MACR;&安培;度;&安培; plusmn;&安培; SUP2;&安培; SUP3;&安培;急性;&安培;微;&安培;对;&安培; middot;&安培; cedil;&安培; SUP1;&安培; ORDM;&安培; RAQUO;&安培; frac14;&安培; frac12;&安培; frac34;&安培; iquest;&安培; Agrave;&安培; Aacute;&安培; ACIRC;&安培; Atilde;&安培; AUML ;&安培; Aring;&安培; AElig;&安培; Ccedil;&安培; Egrave;&安培; Eacute;&安培; Ecirc;&安培; Euml;&安培; Igrave;&安培; Iacute;&安培; Icirc;&安培; IUML;&安培; ETH;&安培; Ntilde;&安培; Ograve;&安培; Oacute;&安培; Ocirc;&安培; Otilde;&安培; Ouml;&安培;倍;&安培; Oslash;&安培; Ugrave;&安培; Uacute;&安培; Ucirc;&安培; Uuml;&安培; Yacute ;&安培; THORN;&安培;大街;&安培; agrave;&安培; aacu TE;&安培; ACIRC;&安培; atilde;&安培; AUML;&安培; aring;&安培; aelig;&安培; ccedil;&安培; egrave;&安培; eacute;&安培; ecirc;&安培; euml;&安培; igrave;&安培; iacute; &安培; icirc;&安培; IUML;&安培; ETH;&安培; ntilde;&安培; ograve;&安培; oacute;&安培; ocirc;&安培; otilde;&安培; ouml;&安培;除法;&安培; oslash;&安培; ugrave;&安培; uacute;&安培; ucirc;&安培; uuml;&安培; yacute;&安培;刺;&安培; yuml;&放大器;放大器;&安培; QUOT;&安培;#039;&安培; LT;&安培; GT;
答案 0 :(得分:1)
您的观察是正确的SimpleXMLElement::addChild()
(和::addAttribute()
)将(仅)某些特殊字符转换为实体。
这是逐字输入一些字符(特别是&符号“&
”字符)。
但是你不希望在你的情况下这样做。要转换所有特殊字符,您需要通过属性访问设置XML元素的文本值,例如:
$entry->Content = $content;
如您所见,未使用$entry->addChild('Content', $content)
,而是使用属性访问$entry->Content
。只有插入一个Content
元素时,该属性访问才有效。如果要向同一父项插入多个,则必须使用所谓的simplexml-self-reference。现在再次演示 addChild()
:
$entry->addChild('Content')->{0} = $content;
完整示例:
$content = "I love &pizza; in the … morning's – night as well";
$xml = new SimpleXMLElement("<Entries />");
$entry = $xml->addChild('Entry');
$entry->Content = $content;
$entry->addChild('Content')->{0} = $content;
echo $xml->asXML();
输出(美化):
<?xml version="1.0"?>
<Entries>
<Entry>
<Content>I love &pizza; in the … morning's – night as well</Content>
<Content>I love &pizza; in the … morning's – night as well</Content>
</Entry>
</Entries>
我希望现在不会太混乱。
除了&符号的问题之外,您可能会看到一些字符编码问题。对于那些有一个简单的规则:每当您将字符串传递给 SimpleXMLElement 时,该字符串的编码必须是UTF-8。
因此,如果您从网站上获取HTML表单中的数据,请注意浏览器会将数据UTF-8编码 - 或者 - 将数据重新编码为UTF-8,然后再将其传递给 SimpleXMLElement 强>