За последние 24 часа нас посетили 16835 программистов и 1644 робота. Сейчас ищут 1057 программистов ...

Проблемы с XSLTProcessor

Тема в разделе "Прочие вопросы по PHP", создана пользователем e-v-g-e-n-y, 14 авг 2008.

  1. e-v-g-e-n-y

    e-v-g-e-n-y Активный пользователь

    С нами с:
    14 авг 2008
    Сообщения:
    3
    Симпатии:
    0
    Всем добрый день.
    Народ, помогите кто может, никогда не работал с XSLT и тут пришлось...
    Я хочу преобразовать контент из FCK редактора в WordML. Сложного ничего нет, но запнулся на самом простом - XSLTProcessor.

    У меня есть класс, в котором метод, принимающий контент от FCK редактора и возвращающий результат:

    Код (Text):
    1. <?php
    2.  
    3. class MY_HTML_TO_DOC
    4. {
    5. function Generate($xmlData)
    6. {
    7. $xml = new DOMDocument;
    8. $xml->loadXML("<div id='mainXMLDiv'>".$xmlData."</div>");
    9.  
    10. $xsl = new DOMDocument;
    11. $xsl->load('mytranslator.xsl');
    12.  
    13. // Configure the transformer
    14. $proc = new XSLTProcessor;
    15. $proc->importStyleSheet($xsl);
    16.  
    17. return $proc->transformToXML($xml);
    18. }
    19. }
    20.  
    21. ?>

    Для простоты, переменная $xmlData равна "<u>HELLO</u>"

    А вот непосредственно и сам XSLT файл:

    Код (Text):
    1. <?xml version="1.0" encoding="windows-1251"?>
    2.  
    3. <!DOCTYPE xsl:stylesheet [
    4. <!ENTITY nbsp "&#x20;">
    5. <!ENTITY copy "©">
    6. <!ENTITY reg "®">
    7. <!ENTITY trade "™">
    8. <!ENTITY mdash "—">
    9. <!ENTITY ldquo "“">
    10. <!ENTITY rdquo "”">
    11. <!ENTITY pound "£">
    12. <!ENTITY yen "¥">
    13. <!ENTITY euro "?">
    14. ]>
    15. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:v="urn:schemas-microsoft-com:vml">
    16. <xsl:output method="html" encoding="windows-1251" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"/>
    17. <xsl:template match="/">
    18. <html>
    19. <head>
    20. <meta http-equiv="Content-Type" content="text/html; charset=windows-1251"/>
    21. <title>
    22. <xsl:apply-templates select="w:wordDocument/o:DocumentProperties"/>
    23. </title>
    24. </head>
    25. <body>
    26. <xsl:apply-templates select="w:wordDocument/w:body/wx:sect"/>
    27. </body>
    28. </html>
    29. </xsl:template>
    30.  
    31. <xsl:template match="w:wordDocument/o:DocumentProperties">
    32. <xsl:value-of select="o:Title"/>
    33. </xsl:template>
    34.  
    35. <xsl:template match="w:wordDocument/w:body/wx:sect">
    36. <xsl:apply-templates />
    37. </xsl:template>
    38.  
    39.  
    40. <!-- HEADINGS and PARA -->
    41. <xsl:template match="w:p">
    42. <xsl:choose>
    43. <xsl:when test="w:pPr/w:pStyle/@w:val=1">
    44. <h1>
    45. <xsl:apply-templates select="w:r | w:hlink" />
    46. </h1>
    47. </xsl:when>
    48. <xsl:when test="w:pPr/w:pStyle/@w:val=2">
    49. <h2>
    50. <xsl:apply-templates select="w:r | w:hlink" />
    51. </h2>
    52. </xsl:when>
    53. <xsl:when test="w:pPr/w:pStyle/@w:val=3">
    54. <h3>
    55. <xsl:apply-templates select="w:r | w:hlink" />
    56. </h3>
    57. </xsl:when>
    58. <xsl:otherwise>
    59. <p>
    60. <xsl:apply-templates select="w:r | w:hlink" />
    61. </p>
    62. </xsl:otherwise>
    63. </xsl:choose>
    64. </xsl:template>
    65.  
    66. <!-- Simple formatting (bold, italic, underline), images -->
    67. <xsl:template match="w:r">
    68. <xsl:choose>
    69. <xsl:when test="w:rPr/w:b"><b><xsl:value-of select="w:t" /></b></xsl:when>
    70. <xsl:when test="w:rPr/w:u"><u><xsl:value-of select="w:t" /></u></xsl:when>
    71. <xsl:when test="w:rPr/w:i"><i><xsl:value-of select="w:t" /></i></xsl:when>
    72. <xsl:otherwise><xsl:value-of select="w:t" /></xsl:otherwise>
    73. </xsl:choose>
    74. </xsl:template>
    75.  
    76. <!-- Parse hyperlinks -->
    77. <xsl:template match="w:hlink">
    78. <a href="{@w:dest}"><xsl:value-of select="w:r/w:t" /></a>
    79. </xsl:template>
    80.  
    81. <!-- Parse table (colspan supported, no rowspans) -->
    82. <xsl:template match="w:tbl">
    83. <table width="100%" cellpadding="0" cellspacing="0" border="1">
    84. <xsl:for-each select="w:tr">
    85. <tr>
    86. <xsl:for-each select="w:tc/w:p">
    87. <xsl:if test="../w:tcPr/w:gridSpan/@w:val > 0">
    88. <xsl:text disable-output-escaping="yes"><td colspan=</xsl:text>
    89. <xsl:value-of select="../w:tcPr/w:gridSpan/@w:val" /><xsl:text disable-output-escaping="yes">"></xsl:text>
    90. </xsl:if>
    91. <xsl:if test="not(../w:tcPr/w:gridSpan/@w:val)">
    92. <xsl:text disable-output-escaping="yes"><td></xsl:text>
    93. </xsl:if>
    94. <xsl:apply-templates select="w:r" />
    95. <xsl:text disable-output-escaping="yes"></td></xsl:text>
    96. </xsl:for-each>
    97. </tr>
    98. </xsl:for-each>
    99. </table>
    100. </xsl:template>
    101.  
    102. </xsl:stylesheet>
    Свой класс я использую так:

    Код (Text):
    1. $mhtd = new MY_HTML_TO_DOC();
    2. $transformed = $mhtd->Generate($resumeHTML);
    3. $fd = fopen('test.doc','w+');
    4. fwrite($fd,$transformed);
    5. fclose($fd);
    В итоге создается файл test.doc и содержит такой контент:

    Код (Text):
    1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    2. <html xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:v="urn:schemas-microsoft-com:vml">
    3. <head>
    4. <meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
    5. <title></title>
    6. </head>
    7. <body></body>
    8. </html>
    Т.е.: XSLTProcessor свою работу делает, но частично, не обрабатывая <U> теги...

    Народ, подскажите пожалуйста, а почему так происходит?

    Заранее очень благодарю!
     
  2. AlexGousev

    AlexGousev Активный пользователь

    С нами с:
    25 мар 2006
    Сообщения:
    1.505
    Симпатии:
    0
    Адрес:
    Москва
    Потому что в приведенном xsl-е нет обработчика тегов u.
    Есть обработчик корневого тега - он выводится.
     
  3. e-v-g-e-n-y

    e-v-g-e-n-y Активный пользователь

    С нами с:
    14 авг 2008
    Сообщения:
    3
    Симпатии:
    0
    Большое спасибо за ответ, Алекс.
    А разве следующая строка не обрабатывает теги <u>?:

    Код (Text):
    1. <xsl:when test="w:rPr/w:u"><u><xsl:value-of select="w:t" /></u></xsl:when>
    я нашел данный xsl не помню где:), но человек утверждал, что он работает прекрасно.... не понимаю((
     
  4. AlexGousev

    AlexGousev Активный пользователь

    С нами с:
    25 мар 2006
    Сообщения:
    1.505
    Симпатии:
    0
    Адрес:
    Москва
    e-v-g-e-n-y
    Сорри, не увидел эту строчку. Она обрабатывает теги <u> с неймспейсом "w", т.е. $xmlData должна быть равна "<w:u>HELLO</w:u>".
     
  5. AlexGousev

    AlexGousev Активный пользователь

    С нами с:
    25 мар 2006
    Сообщения:
    1.505
    Симпатии:
    0
    Адрес:
    Москва
    А нет, не все так просто: сейчас напишу много текста :)
     
  6. AlexGousev

    AlexGousev Активный пользователь

    С нами с:
    25 мар 2006
    Сообщения:
    1.505
    Симпатии:
    0
    Адрес:
    Москва
    Во-первых, надо понять как делается преобразование. Все идет строго по иерархии. Как правило, первым определяется шаблон для корневого тега:
    Код (Text):
    1. <xsl:template match="/">
    Внутри это шаблона инициализируются преобразования тегов: w:wordDocument/o:DocumentProperties и w:wordDocument/w:body/wx:sect:
    Код (Text):
    1. <xsl:apply-templates select="w:wordDocument/o:DocumentProperties"/>
    2. <xsl:apply-templates select="w:wordDocument/w:body/wx:sect"/>
    А из этого следует, что данное преобразование понимает следующую структуру документа: структура исходного документа должна начинаться с корневого тега w:wordDocument, который в свою очередь может содержать теги o:DocumentProperties и w:body. Причем w:body может содержать в себе теги wx:sect.
    Все это вовсе не значит, что в документе не может быть других тегов, а значит, что преобразование понимает только их.

    Дальше смотрим преобразование w:wordDocument/o:DocumentProperties:
    Код (Text):
    1. <xsl:template match="w:wordDocument/o:DocumentProperties">
    2.     <xsl:value-of select="o:Title"/>
    3. </xsl:template>
    Здесь берется значение тега o:Title, являющегося вложенным в тег o:DocumentProperties.

    Аналогично нужно посмотреть как развертывается w:wordDocument/w:body/wx:sect.
     
  7. AlexGousev

    AlexGousev Активный пользователь

    С нами с:
    25 мар 2006
    Сообщения:
    1.505
    Симпатии:
    0
    Адрес:
    Москва
  8. e-v-g-e-n-y

    e-v-g-e-n-y Активный пользователь

    С нами с:
    14 авг 2008
    Сообщения:
    3
    Симпатии:
    0
    Алекс, огромное Вам спасибо!

    Я понял главное - что этот xsl для преобразования WordML в HTML, а я от него ожидал обратного эфекта (из HTML в WordML). Сам алгоритм не сложен, но туториал обязательно почитаю.

    Еще раз спасибо Вам!;)