PHP - класс DOM - проблема с нумерованными сущностями и кодировками - PullRequest
2 голосов
/ 19 мая 2010

У меня возникли сложности с классом PHP DOM.

Я делаю сценарий карты сайта, и мне нужно, чтобы вывод $ doc-> saveXML () был похож на

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <url>
        <loc>http://www.somesite.com/servi&#xE7;os/redesign</loc>
    </url>
</root>

или

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <url>
        <loc>http://www.somesite.com/servi&#231;os/redesign</loc>
    </url>
</root>

но я получаю:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <url>
        <loc>http://www.somesite.com/servi&amp;#xE7;os/redesign</loc>
    </url>
</root>

Это шкаф, который я мог получить, используя функцию замены именованных сущностей.

Мне также удалось воспроизвести

<?xml version="1.0" ?>
<root>
    <url>
        <loc>http://www.somesite.com/servi&amp;#xE7;os/redesign</loc>
    </url>
</root>

Но без указанной кодировки.

Лучшее решение (как я думаю, код должен быть написан) было бы:

<?php
$myArray = array();
// do some stuff to populate the with URL strings

$doc = new DOMDocument('1.0', 'UTF-8');

// here we modify some property. Maybe is the answer I am looking for...

$urlset = doc->createElement("urlset");
$urlset = $doc->appendChild($urlset);

foreach($myArray as $address) {
    $url = $doc->createElement("url");
    $url = $urlset->appendChild($url);

    $loc = $doc->createElement("loc");
    $loc = $url->appendChild($loc);

    $valueContent = $doc->createTextNode($value);
    $valueContent = $loc->appendChild($address);
}

echo $doc->saveXML();
?>

Примечания:

  • Заголовок ответа сервера содержит кодировку UTF-8;
  • PHP-скрипт сохраняется в UTF-8;
  • прочитанные URL - это строки UTF-8;
  • Вышеуказанный скрипт содержит объявление кодировки в конструкторе DOMDocument и не использует никаких функций преобразования, таких как htmlentities, urlencode, utf8_encode ...

Я попытался изменить свойства DOMDocument DOMDocument :: $ resolExternals и DOMDocument :: $ substituteEntities значения. Ни одна комбинация не сработала.

И да, я знаю, что могу выполнить весь процесс без указания набора символов в конструкторе DOMDocument, выгрузить содержимое строки в переменную и выполнить очень простую подстановку строк с помощью функций замены строк. Это работает. Но я хотел бы знать, где я проскальзываю, как это можно сделать с помощью встроенных API и настроек или даже если это возможно.

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 19 мая 2010

resolveExternals и substituteEntities являются функциями синтаксического анализатора. Они не влияют на сериализацию.

Инфо-набор XML не делает никаких различий между:

<loc>http://www.somesite.com/serviços/redesign</loc>
<loc>http://www.somesite.com/servi&#xE7;os/redesign</loc>
<loc>http://www.somesite.com/servi&#231;os/redesign</loc>

все они представляют одну и ту же информацию, любой синтаксический анализатор XML должен рассматривать их как идентичные, а сериализаторы XML, как правило, не позволяют выбирать, какой выводить. Обычно вы должны просто установить значение текстового узла, чтобы оно включало ç, и позволить сериализатору записать его в ç, как необработанную байтовую строку UTF-8 в выводе.

Если вам действительно нужно сгенерировать файл XML, который содержит только ASCII, поэтому вы не можете напрямую использовать такие символы, как ç, тогда скажите PHP использовать ASCII в качестве кодировки документа:

$s= "serviços"; // or "\xC3\xA7" if you can't input UTF-8 strings directly

$doc = new DOMDocument('1.0', 'US-ASCII');
$doc->appendChild($loc= $doc->createElement('loc'));
$loc->appendChild($doc->createTextNode($s));
echo $doc->saveXML();

результат:

<?xml version="1.0" encoding="US-ASCII"?>
<loc>servi&#231;os</loc>

Однако ... сказав все это, я все еще не думаю, что это правильно. Ваше значение представляется URL-адресом, и символы, не входящие в ASCII, недопустимы в URL-адресах независимо от того, как они закодированы в содержащем XML. Должно быть:

http://www.somesite.com/servi%C3%A7os/redesign

т. rawurlencode('serviços').

0 голосов
/ 19 мая 2010

Расшифруйте свои объекты перед передачей в createTextNode

$valueContent = $doc->createTextNode(html_entity_decode($value, ENT_QUOTES, 'UTF-8'));

Это потому, что ç не является допустимым объектом в документе UTF-8. Таким образом, DomDocument видит & и кодирует его как & amp;

...