php:每当我尝试编写UTF-8时都使用DomDocument,它会写入十六进制表示法

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>&#x5D9;&#x5E8;&#x5D5;&#x5E9;&#x5DC;&#x5D9;&#x5DD;</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)

它将按预期工作.

或者,您也可以在加载文档后指定编码.


hak*_*kre 6

如果要使用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>&#x5D9;&#x5E8;&#x5D5;&#x5E9;&#x5DC;&#x5D9;&#x5DD;</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>&#x5D9;?????? <![CDATA[???????]]></root>");
$dom->save('php://output');
Run Code Online (Sandbox Code Playgroud)

输出:

<?xml version="1.0"?>
<!-- ??????? -->
<root>&#x5D9;&#x5E8;&#x5D5;&#x5E9;&#x5DC;&#x5D9;&#x5DD; <![CDATA[???????]]></root>
Run Code Online (Sandbox Code Playgroud)

得到教训:

提示:如果您的字符串具有与字符串编码不匹配的XML声明,或者您希望将字符串加载到 DOMDocument 之前更改其中任何一个,则需要更改XML声明和/或重新编码字符串.这已经PHP XMLReader问题的答案得到了解释,通过展示XMLRecoder类的工作原理来获取版本和编码.

这是有希望的.


[1]可能如果您从HTTP请求加载并提供流上下文并通过元数据标记字符编码 - 但这应该先测试,我不知道.BOM不起作用有点表明所有这些都不起作用.