hex2bin - php: utilizando DomDocument cada vez que intento escribir UTF-8 escribe la notación hexadecimal de él
raw to hex (6)
Cuando intento escribir cadenas UTF-8 en un archivo XML utilizando DomDocument, escribe la notación hexadecimal de la cadena en lugar de la cadena misma.
por ejemplo:
ירושלים
en lugar de: ירושלים
alguna idea de cómo resolver el problema?
Aparentemente pasar el elemento documentElement como $ node para guardarXML funciona alrededor de esto, aunque no puedo decir que entiendo por qué.
p.ej
$dom->saveXML($dom->documentElement);
más bien que:
$dom->saveXML();
Fuente: http://www.php.net/manual/en/domdocument.savexml.php#88525
Cuando creé DomDocument para escribir, agregué los siguientes parámetros:
dom = new DOMDocument(''1.0'',''utf-8'');
estos parámetros causaron que la cadena UTF-8 se escriba como está.
Hasta el punto la respuesta es:
Cuando se inicia su función, justo después de obtener el contenido, haga esto:
$content = mb_convert_encoding($content, ''HTML-ENTITIES'', ''UTF-8'');
Y luego inicie el nuevo documento, etc. Marque esto como ejemplo:
if ( empty( $content ) ) {
return false;
}
$doc = new DOMDocument(''1.0'', ''utf-8'');
libxml_use_internal_errors(true);
$doc->LoadHTML($content, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
Luego haz lo que tengas pensado hacer con tu código.
OK aquí tienes:
$dom = new DOMDocument(''1.0'', ''utf-8'');
$dom->appendChild($dom->createElement(''root''));
$dom->documentElement->appendChild(new DOMText(''ירושלים''));
echo $dom->saveXml();
funcionará bien, porque en este caso, el documento que construyó conservará la codificación especificada como el segundo argumento:
<?xml version="1.0" encoding="utf-8"?>
<root>ירושלים</root>
Sin embargo, una vez que carga XML en un documento que no especifica una codificación, perderá todo lo que haya declarado en el constructor, lo que significa:
$dom = new DOMDocument(''1.0'', ''utf-8'');
$dom->loadXml(''<root/>''); // missing prolog
$dom->documentElement->appendChild(new DOMText(''ירושלים''));
echo $dom->saveXml();
no tendrá una codificación de utf-8:
<?xml version="1.0"?>
<root>ירושלים</root>
Entonces, si cargas algo de XML, asegúrate de que sea
$dom = new DOMDocument();
$dom->loadXml(''<?xml version="1.0" encoding="utf-8"?><root/>'');
$dom->documentElement->appendChild(new DOMText(''ירושלים''));
echo $dom->saveXml();
y funcionará como se esperaba.
Como alternativa, también puede especificar la codificación después de cargar el documento.
Si desea generar UTF-8 con DOMDocument, debe especificar eso. Simple, ¿no es así? Si ya hueles una pregunta capciosa, no estás muy lejos, pero a primera vista, realmente es sencillo.
Considere el siguiente ejemplo de código (codificado en UTF-8) que ejemplifica entidades hexadecimales:
$dom = new DOMDocument();
$dom->loadXml(''<root>ירושלים</root>'');
$dom->save(''php://output'');
Salida:
<?xml version="1.0"?>
<root>ירושלים</root>
Tal como está escrito, si desea imprimir esto como UTF-8, debe especificarlo, y es sencillo:
...
$dom->encoding = ''UTF-8'';
$dom->save(''php://output'');
El resultado está en UTF-8 explícitamente :
<?xml version="1.0" encoding="UTF-8"?>
<root>ירושלים</root>
Demasiado para la parte directa. Si le interesan los pequeños y sucios detalles, puede seguir leyendo, si no, no pregunte "¿por qué?" :).
Acabo de escribir " explícitamente en UTF-8" porque también en el primer ejemplo, la salida está codificada en UTF-8, el XML solo contenía entidades hexadecimales, lo que es perfectamente válido, ¡incluso en UTF-8!
Ya has notado que empiezo con el pick-ning aquí, pero recuerda: UTF-8 es la codificación predeterminada de XML .
Y si ahora comienzas a decir: Oye, espera, si la codificación predeterminada es UTF-8 de todos modos, ¿por qué DOMscument de PHP usa las entidades en primer lugar?
Bueno, la verdad es que no es contrario al hallazgo en la pregunta. No siempre
Vea el siguiente ejemplo que está usando un comentario XML en lugar de un valor de nodo que contiene las letras de Ivrit:
$dom = new DOMDocument();
$dom->loadXml(''<root><!-- ירושלים --></root>'');
$dom->save(''php://output'');
Salida:
<?xml version="1.0"?>
<root><!-- ירושלים --></root>
De acuerdo, todo claro? Entonces, el pequeño y sucio secreto aquí es: si tienes esas entidades XML allí o no, para el documento no hace una diferencia, es solo una forma diferente de escribir los mismos datos de caracteres XML. Y ya te sientes invitado: vamos a probar CDATA en lugar del primer ejemplo:
$dom = new DOMDocument();
$dom->loadXML("<root><![CDATA[ירושלים]]></root>");
$dom->save(''php://output'');
Salida:
<?xml version="1.0"?>
<root><![CDATA[ירושלים]]></root>
Como esto se demuestra con el ejemplo de comentario XML anterior, aquí no se usan entidades XML. Bueno, de todos modos no serían válidos, como con el ejemplo de comentario XML.
Para obtener información general, crea un ejemplo que contenga todo esto:
$dom = new DOMDocument();
$dom->loadXML("<!-- ירושלים --><root>ירושלים <![CDATA[ירושלים]]></root>");
$dom->save(''php://output'');
Salida:
<?xml version="1.0"?>
<!-- ירושלים -->
<root>ירושלים <![CDATA[ירושלים]]></root>
Lecciones aprendidas:
- UTF-8 siempre se usa. Solo algunas entidades se usan en PCDATA a menos que se especifique la codificación UTF-8. Si se especifica una codificación diferente a UTF-8, se aplican reglas diferentes .
- No puede especificar si desea usar entidades o no para la salida cargando un documento XML como una cadena codificada en UTF-8 en PHP DOMDocument per-se. Ni siquiera con los indicadores libxml ni proporcionando una lista de materiales. [1]
- Puede especificar que no desea usar entidades configurando la codificación de documentos en UTF-8.
- Si puede, puede manipular la cadena de entrada que tiene una Declaración XML que especifica la codificación de documentos como se indica en la respuesta de Gordon .
Consejo: Si su cadena tiene una Declaración XML que no coincide con la codificación de cadenas o si desea cambiar cualquiera de las dos antes de cargar la cadena en DOMDocument , necesita cambiar la Declaración XML y / o volver a codificar la cadena. Esto se ha cubierto en una respuesta a la pregunta PHP XMLReader, obtenga la versión y la codificación mostrando cómo funciona la clase
XMLRecoder
.
Y eso es todo con suerte.
[1] Probablemente, si carga desde una solicitud HTTP y proporciona un contexto de transmisión y marca la codificación de caracteres a través de metadatos, pero esto debe probarse primero, no lo sé. Que el BOM no funcione es una señal de que todas estas cosas no funcionan.
$doc = new DOMDocument();
$doc->loadHTML(''<?xml encoding="UTF-8">'' . $html);
// dirty fix
foreach ($doc->childNodes as $item)
if ($item->nodeType == XML_PI_NODE)
$doc->removeChild($item); // remove hack
$doc->encoding = ''UTF-8''; // insert proper