Как вывести элемент документа XML в виде строки, которая имеет ту же кодировку, что и документ? - PullRequest
0 голосов
/ 07 февраля 2020

Так, например, документ XML в кодировке ISO-8859-1, который даже содержит некоторые символы, которые не являются частью набора символов этой кодировки, скажем, символ € (евро). Это возможно в XML, если символ представлен как символьная сущность Юникода, в этом случае строка € (евро):

<?xml version="1.0" encoding="ISO-8859-1"?>
<foo>
    <bar>&#8364;</bar>
</foo>

Мне нужно получить бар Строка элемента с той же кодировкой, что и в документе, что означает кодирование в ISO-8859-1 (также означает сохранение объектов символов Юникода, которые не являются частью этой кодировки), то есть строка ISO-8859-1 <bar>&#8364;</bar>.

Я не смог добиться этого с помощью метода save XML класса DOMDocument, поскольку он всегда выгружает элементы в UTF-8 (тогда как целые документы всегда в кодировке их объявления XML):

$DD = new DOMDocument;
$DD -> load('foo.xml');
$dump = $DD -> saveXML($DD -> getElementsByTagName('bar') -> item(0));

Переменная $dump привела к появлению строки UTF-8 <bar>€</bar>.

Обратите внимание, что элементы выгружаются также с объектами Unicode, преобразованными в фактические символы UTF-8.

Итак, как мне получить строку ISO-8859-1 <bar>&#8364;</bar>? XML парсеры предназначены для выполнения такого рода задач или я должен просто использовать регулярные выражения для чего-то еще?

Ответы [ 2 ]

1 голос
/ 08 февраля 2020

Похоже, кодировка не используется, когда saveXML() используется с аргументом узла. Когда вы устанавливаете свойство $encoding в классе DOMDocument, оно будет использоваться в функции saveXML(), но только при сохранении всего документа. Проверив исходный код функции saveXML() , вы увидите даже комментарий, в котором упоминается свойство encoding:

if (nodep != NULL) {
    [...]
} else {
    [...]
    /* Encoding is handled from the encoding property set on the document */
    xmlDocDumpFormatMemory(docp, &mem, &size, format);
}

Согласно объектной модели документа (DOM) Уровень 3 Спецификация загрузки и сохранения множество определенных типов поддерживают настройку кодировки (и реализация PHP имеет ее, по крайней мере, для класса DOMDocument). Поэтому я не уверен, что это ошибка в реализации DOM в PHP. Однако в документации также указывается, что в нем используется кодировка UTF-8:

Примечание:

Расширение DOM использует кодировку UTF-8. Используйте utf8_encode() и utf8_decode() для работы с текстами в кодировке ISO-8859-1 или iconv для других кодировок.

Таким образом, решение состоит в том, чтобы использовать такие функции для преобразования его в правильный результат или сохраните весь документ XML с saveXML() без каких-либо аргументов.

1 голос
/ 08 февраля 2020

Да, они будут декодировать объекты, и если вы сохраните только часть документа, это будет UTF-8, потому что он не может указать кодировку - по умолчанию он возвращается к UTF-8.

Здесь это демо:

$xml = <<<'XML'
<?xml version="1.0" encoding="ISO-8859-1"?>
<foo>
    <bar>&#8364;</bar>
</foo>
XML;

$source = new DOMDocument();
$source->loadXML($xml);

echo "Document Part:\n";
echo $source->saveXML($source->getElementsByTagName('bar')->item(0));
echo "\n\n";

echo "Whole Document:\n";
echo $source->saveXML();
echo "\n\n";

Вывод:

Document Part:
<bar>€</bar>

Whole Document:
<?xml version="1.0" encoding="ISO-8859-1"?>
<foo>
    <bar>&#8364;</bar>
</foo>

Вы можете скопировать узел в новый документ. Однако выходные данные будут включать объявление XML с кодировкой:

$target = new DOMDocument('1.0', 'ASCII');
$target->appendChild($target->importNode($source->getElementsByTagName('bar')->item(0), true));

echo "Separated Node:\n";
echo $target->saveXML();

Выходные данные:

Separated Node:
<?xml version="1.0" encoding="ASCII"?>
<bar>&#8364;</bar>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...