Xpoint
   [напомнить пароль]

Трансформация XML в XHTML средствами PHP5

Метки: [без меток]
2009-05-17 21:25:28 [обр] AndrewM[досье]

Вопрос в следующем.
Как получить из XML – XHTML, да еще и без DOCTYPE ?
Почему без DOCTYPE? Потому что полученный кусок я встраиваю в середину шаблона на PHP.
Варианты решения.

  1. Если в XSL-файле поставить
<xsl:output method="html" indent="yes" omit-xml-declaration="yes" encoding="windows-1251"/>

- все тэги типа <br / > превращаются в <br>

  1. Если в XSL-файле поставить
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" encoding="windows-1251"/>

- то тэги типа <textarea></textarea> ревращаются в <textarea />

  1. Если в XSL-файле поставить
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" 
doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" 
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" 
encoding="windows-1251"/>

- то перед полученным XHTML появляется DOCTYPE.

Как быть?

спустя 2 часа 17 минут [обр] Marat Tanalin(0/78)[досье]
Вырезать DOCTYPE из результирующего кода, его содержащего?
спустя 4 минуты [обр] AndrewM[досье]
Да, можно, но ИМХО не красиво...
Может быть еще есть какие-нибудь способы?
спустя 17 часов [обр] Александр Лукьянов(221/781)[досье]
А в XSL есть шаблон, который выводит <html></html>? Если его убрать (Вы же результат в "середину шаблона" встраиваете) и генерить только нужный фрагмент XHTML, доктайп остается?
спустя 5 часов [обр] AndrewM[досье]

Вы имеете в виду конструкцию вроде:

<xsl:template match="/">
  <html>
    <xsl:apply-templates />
  </html>
</xsl:template>

Нет, ничего подобного у меня нет.
Да и PHP-процессор <html> сам не добавляет, генеря странный документ, вида, допустим:

<!DOCTYPE ... >
<p>...</p>

Вообще мой вопрос где-то на стыке XSL и PHP. Может быть в PHP можно как-то извратиться..?

спустя 17 часов [обр] Александр Лукьянов(221/781)[досье]

Это в принципе, по спецификации требуется.
Я подозреваю, что Вам проще всего будет оставить xsl:output с правильным доктайпом, но результат преобразования сериализовать не напрямую

$resStr = $xsltProc -> transformToXML($DOM);

а преобразуя в DOMDocument и затем сериализуя только элемент документа

$resDOM = $xsltProc -> transformToDoc($DOM);
$resStr = $resDOM -> saveXML($resDOM -> documentElement);

Так вроде и документ результирующий строится по правилам XHTML и сериализуется нормально (пустые non-empty элементы типа textarea не схлопываются, пустые empty элементы типа br не разворачиваются).

спустя 5 дней [обр] AndrewM[досье]

Мда... В общем - спасибо, направление правильное ;)
Но вылезает еще пара глюков.
Во-первых, если документ не имеет корневого элемента - то возвращается только первый встретившийся элемент.
Как может быть, что XML не имеет корневого элемента? Сам не знаю ;), но такие результаты генерит PHP если XSL имеет вид:

<xsl:template match="/"> 
  <xsl:apply-templates /> 
</xsl:template>

И во-вторых, результаты выводятся в UTF-8... Видимо по тому, что вместе с водой мы выплеснули и кодировку:

<?xml version="1.0" encoding="windows-1251"?>

Продолжаю копаться. Если еще кто-нибудь что-нибудь придумает - буду благодарен ;)

спустя 15 часов [обр] Александр Лукьянов(221/781)[досье]

Не буду утверждать на 100% (экспериментировал в свое время, не помню сейчас), но вроде XSL-процессор и на вход может принимать документы с несколькими корневыми элементами (например, созданный DOM-методами, а не из XML-файла), и на выходе может совершенно спокойно генерить "лес" вместо дерева.
Если у Вас после трансформации получается "лес" и этот результат нормально сохраняется в DOMDocument, то вытащить из него все "корни" можно циклом, иначе придется на всякий случай вводить фиктивный корень, типа:

<xsl:template match="/">
  <div>
    <xsl:apply-templates/>
  </div>
<xsl:template>

С кодировкой - попробуйте явно указать свойство DOMDocument -> encoding = "windows-1251", т.е. как-то так:

$resDOM = $xsltProc -> transformToDoc($DOM);
$resDOM -> encoding = "windows-1251";
$resStr = $resDOM -> saveXML($resDOM -> documentElement);

Не проверил, но вероятно, сработает.

спустя 10 часов [обр] AndrewM[досье]

Не, $resDOM -> encoding = "windows-1251"; - не помогает :(
Дело в том, что

$resDOM -> saveXML();

 - вообще корректно выводится по-русски, а стоит только добавить

$resDOM -> saveXML($resDOM -> documentElement);

- как сразу - в UTF.
Т.е. добавляем мы кодировку ко всему документу, а как только запрашиваем один его элемент - PHP про кодировку забывает...

Powered by POEM™ Engine Copyright © 2002-2005