ufk*_*ufk 11 php utf-8 hebrew domdocument
当我尝试使用DomDocument将UTF-8字符串写入XML文件时,它实际上写入字符串的十六进制表示法而不是字符串本身.
例如:
__CODE__
而不是:ירושלים
任何想法如何解决这个问题?
Gor*_*don 17
好的,你走了:
$dom = new DOMDocument('1.0', 'utf-8');
$dom->appendChild($dom->createElement('root'));
$dom->documentElement->appendChild(new DOMText('???????'));
echo $dom->saveXml();
Run Code Online (Sandbox Code Playgroud)
将正常工作,因为在这种情况下,您构造的文档将保留指定为第二个参数的编码:
<?xml version="1.0" encoding="utf-8"?>
<root>???????</root>
Run Code Online (Sandbox Code Playgroud)
但是,一旦将XML加载到未指定编码的Document中,您将丢失在构造函数中声明的任何内容,这意味着:
$dom = new DOMDocument('1.0', 'utf-8');
$dom->loadXml('<root/>'); // missing prolog
$dom->documentElement->appendChild(new DOMText('???????'));
echo $dom->saveXml();
Run Code Online (Sandbox Code Playgroud)
将不具有utf-8的编码:
<?xml version="1.0"?>
<root>ירושלים</root>
Run Code Online (Sandbox Code Playgroud)
因此,如果你加载XML,确保它是
$dom = new DOMDocument();
$dom->loadXml('<?xml version="1.0" encoding="utf-8"?><root/>');
$dom->documentElement->appendChild(new DOMText('???????'));
echo $dom->saveXml();
Run Code Online (Sandbox Code Playgroud)
它将按预期工作.
或者,您也可以在加载文档后指定编码.
如果要使用DOMDocument输出UTF-8,则需要指定.简单,不是吗?如果你已经闻到一个棘手的问题,那你就不会太遥远,但初看起来,它确实是直截了当的.
考虑以下(UTF-8编码)代码示例,它输出十六进制实体:
$dom = new DOMDocument();
$dom->loadXml('<root>???????</root>');
$dom->save('php://output');
Run Code Online (Sandbox Code Playgroud)
输出:
<?xml version="1.0"?>
<root>ירושלים</root>
Run Code Online (Sandbox Code Playgroud)
如上所述,如果您想将其输出为UTF-8,则需要指定它,并且它是直截了当的:
...
$dom->encoding = 'UTF-8';
$dom->save('php://output');
Run Code Online (Sandbox Code Playgroud)
然后输出显式为UTF-8 :
<?xml version="1.0" encoding="UTF-8"?>
<root>???????</root>
Run Code Online (Sandbox Code Playgroud)
对于直接的部分来说太多了.如果您对肮脏的小细节感兴趣,可以自由阅读 - 如果没有,请不要问"为什么?" :).
我只是写了" 明确地使用 UTF-8 ",因为在第一个例子中输出是UTF-8编码的,XML只包含十六进制实体,它们完全有效 - 即使在UTF-8中也是如此!
您已经注意到我从这里开始挑选,但请记住:UTF-8 是 XML 的默认编码.
如果你现在开始说:嘿等等,如果默认编码是UTF-8,为什么PHP DOMDocument首先使用实体?
事实是,它与问题中的发现并不相反.不总是.
请参阅以下示例,该示例使用XML注释而不是包含Ivrit字母的节点值:
$dom = new DOMDocument();
$dom->loadXml('<root><!-- ??????? --></root>');
$dom->save('php://output');
Run Code Online (Sandbox Code Playgroud)
输出:
<?xml version="1.0"?>
<root><!-- ??????? --></root>
Run Code Online (Sandbox Code Playgroud)
好的,一切都清楚了?所以这里肮脏的小秘密是:你是否有那些XML实体 - 对于文档来说它没有什么区别,它只是编写相同XML字符数据的另一种形式.你已经感受到了邀请:让我们尝试CDATA代替第一个例子:
$dom = new DOMDocument();
$dom->loadXML("<root><![CDATA[???????]]></root>");
$dom->save('php://output');
Run Code Online (Sandbox Code Playgroud)
输出:
<?xml version="1.0"?>
<root><![CDATA[???????]]></root>
Run Code Online (Sandbox Code Playgroud)
正如之前的XML-comment示例所示,此处没有使用XML实体.好吧,无论如何它们都不会有效,就像XML-comment示例一样.
对于概述,我们创建一个包含所有这些的示例:
$dom = new DOMDocument();
$dom->loadXML("<!-- ??????? --><root>י?????? <![CDATA[???????]]></root>");
$dom->save('php://output');
Run Code Online (Sandbox Code Playgroud)
输出:
<?xml version="1.0"?>
<!-- ??????? -->
<root>ירושלים <![CDATA[???????]]></root>
Run Code Online (Sandbox Code Playgroud)
得到教训:
提示:如果您的字符串具有与字符串编码不匹配的XML声明,或者您希望在将字符串加载到 DOMDocument 之前更改其中任何一个,则需要更改XML声明和/或重新编码字符串.这已经在PHP XMLReader问题的答案中得到了解释,通过展示
XMLRecoder类的工作原理来获取版本和编码.
这是有希望的.
[1]可能如果您从HTTP请求加载并提供流上下文并通过元数据标记字符编码 - 但这应该先测试,我不知道.BOM不起作用有点表明所有这些都不起作用.