PHP - htmlentities()是否足以创建xml-safe值?

Joh*_*man 35 php xml xml-serialization

我正在从头构建一个XML文件,需要知道htmlentities()是否会转换每个可能破坏XML文件的字符(可能还有UTF-8数据)?值将来自twitter/flickr feed,所以我需要确定!

Jon*_*Jon 52

htmlentities() 不是保证构建合法XML的方法.

使用htmlspecialchars()而不是htmlentities()如果你担心这一切.如果您的数据表示与XML文档的编码之间存在编码不匹配,则htmlentities()可能会解决/覆盖它们(这样做会使您的XML大小膨胀).我相信最好让你的编码保持一致并且只是使用htmlspecialchars().

另外,请注意,如果您htmlspecialchars()使用单引号分隔内部XML属性的返回值,则还需要传递该ENT_QUOTES标志,以便源字符串中的任何单引号也被正确编码.无论如何,我建议这样做,因为它使您的代码免受因将来使用XML属性的单引号而导致的错误.

编辑:澄清:

htmlentities()将实体(仅用ANSI字符表示)转换为许多非ANSI字符(我假设这是UTF-8数据的含义).但是,对于没有相应实体的任何字符,它不能这样做,因此不能保证其返回值仅包含ANSI字符.这就是为什么我建议不要使用它.

如果编码是一个可能的问题,请明确处理(例如iconv()).

编辑2:考虑到Josh Davis的评论,改进了答案.

  • 不要对XML使用`htmlentities`; 它适用于HTML而不是XML.XML只知道五个实体*amp*,*lt*,*gt*,*apos*和*quot*.但是`htmlentities`会使用更多(那些为HTML注册的). (8认同)
  • 尽管如此,"它将使您的XML保证合法"**的说法不会更加错误.如上所述,htmlentities()使用未在XML中定义的实体.此外,它不会清理不应出现在XML文档中的字节,例如NUL字节.它也不会清除无效的UTF-8,因此在某些情况下,XML解析器可能无法生成结果文档. (4认同)
  • 怎么样`htmlspecialchars($ string,ENT_XML1)` (4认同)

Gor*_*don 20

Dom::createTextNode() 将自动转义您的内容.

例:

$dom = new DOMDocument;
$element = $dom->createElement('Element');
$element->appendChild(
    $dom->createTextNode('I am text with Ünicödé & HTML €ntities ©'));

$dom->appendChild($element);
echo $dom->saveXml();
Run Code Online (Sandbox Code Playgroud)

输出:

<?xml version="1.0"?>
<Element>I am text with &#xDC;nic&#xF6;d&#xE9; &amp; HTML &#x20AC;ntities &#xA9;</Element>
Run Code Online (Sandbox Code Playgroud)

将内部编码设置为utf-8时,例如

$dom->encoding = 'utf-8';
Run Code Online (Sandbox Code Playgroud)

你还会得到

<?xml version="1.0" encoding="utf-8"?>
<Element>I am text with Ünicödé &amp; HTML €ntities ©</Element>
Run Code Online (Sandbox Code Playgroud)

请注意,上面是不一样的设置第二个参数$valueDom::createElement().该方法仅确保您的元素名称有效.请参阅手册页上的注释,例如

$dom = new DOMDocument;
$element = $dom->createElement('Element', 'I am text with Ünicödé & HTML €ntities ©');
$dom->appendChild($element);
$dom->encoding = 'utf-8';
echo $dom->saveXml();
Run Code Online (Sandbox Code Playgroud)

会导致警告

Warning: DOMDocument::createElement(): unterminated entity reference  HTML €ntities ©
Run Code Online (Sandbox Code Playgroud)

以及以下输出:

<?xml version="1.0" encoding="utf-8"?>
<Element>I am text with Ünicödé </Element>
Run Code Online (Sandbox Code Playgroud)


Pet*_*uss 14

戈登的答案很好,并解释了XML编码问题,但没有显示简单的功能(或黑盒做什么).Jon的答案从'htmlspecialchars'函数推荐开始,但他和其他人做了一些错误,然后我会强调.

一个好的程序员必须控制你的字符串和XML数据中是否使用UTF-8:UTF-8(或其他非ASCII编码)在一致的算法中是安全的.

安全的UTF-8 XML不需要全实体编码.不加区分的编码产生"第二类,非人类可读,编码/解码需求,XML".当所有内容都是ASCII时,安全的ASCII XML也不需要实体编码.

只有3或4个字符需要的XML内容的字符串进行转义:>,<,&,和可选的".请阅读http://www.w3.org/TR/REC-xml/"2.4字符数据和标记"和"4.6预定义实体".那么你可以使用' htmlentities '

为了说明,以下PHP函数将使XML完全安全:

// it is a didactic illustration, USE htmlentities($S,flag)
function xmlsafe($s,$intoQuotes=0) {
if ($intoQuotes)
    return str_replace(array('&','>','<','"'), array('&amp;','&gt;','&lt;','&quot;'), $s);
    // SAME AS htmlspecialchars($s)
else
    return str_replace(array('&','>','<'), array('&amp;','&gt;','&lt;'), $s);
    // SAME AS htmlspecialchars($s,ENT_NOQUOTES)
}

// example of SAFE XML CONSTRUCTION
function xmlTag( $element, $attribs, $contents = NULL) {
$out = '<' . $element;
foreach( $attribs as $name => $val )
   $out .= ' '.$name.'="'. xmlsafe( $val,1 ) .'"';
if ( $contents==='' || is_null($contents) )
    $out .= '/>';
else
    $out .= '>'.xmlsafe( $contents )."</$element>";
return $out;
}
Run Code Online (Sandbox Code Playgroud)

在CDATA块中你不需要使用这个功能......但是,请避免不加选择地使用CDATA.


Jos*_*vis 5

所以你的问题是"htmlentities()的结果是否符合XML标准且符合UTF-8标准?" 答案是否定的,但事实并非如此.

htmlspecialchars()应该足以转义XML的特殊字符,但你必须以任何方式清理你的UTF-8字符串.即使您使用SimpleXML构建XML,也必须清理字符串.我不知道其他librairies,如XMLWriter或DOM,我认为它是相同的.