Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > XML, XSL > XML->HTML: Тег ссылки внутри текстового блока


Автор: Karabas 14.6.2006, 12:27
Всем привет!
Я все понимаю, идея XML -- отделения контента от оформления -- гениальная, но бывают ситуации когда этот подход мешает. Попытка вставить гиперссыку в текстовый блок не увенчалась успехом: 
XML:
<page>
    <p>    Text, text, text, text, text, text, text, text, text, text,
        <link href="index.html">And here a link</Plink>
        text, text, text, text, text, text, text, text, text, text,
    </p>
</page>
И из него генерю html. 
Вот такой XSL (это отрывок, остальные части работают нормально) игнорирует начилие тега <link>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
.........
<xsl:template match="p">
<p class="p">
<xsl:value-of select="."/>
</p>
<xsl:apply-templates select="link"/>
</xsl:template>
..........

Если вставлять <xsl:apply-templates select="link"/> в XSL  рядом с <xsl:apply-templates select="p"/> то все ссылки оказываются после текста...  smile 
А как можно иначе (средствами XSL)? 
 

Автор: Beard 14.6.2006, 14:59
В таких случаях лучше использовать секцию CDATA в XML:
Код

<p>
<![CDATA[Text, text, text, text, text, text, text, text, text, text,
        <link href="index.html">And here a link</link>
        text, text, text, text, text, text, text, text, text, text,]]>
</p>

а в шаблоне
Код

<xsl:template match="p">
   <p class="p">
     <xsl:value-of select="." disable-output-escaping = "yes"/>
   </p>
</xsl:template>


Добавлено @ 15:10 
Ну а если не хочется пользоваться CDATA, то можно сделать так:
Код

   <xsl:template match="p">
      <p class="p">
         <xsl:copy-of select="child::node()" />
      </p>
   </xsl:template>
  

Автор: Karabas 16.6.2006, 09:34
Спасибо за ответ.  
CDATA не хотелось использовать, чтобы не загромождать исходный файл, а вариант с child::node работает.  

На данном этапе меня такое решение устраивает, а вообще на будущее можно, ли сделать чтобы XSL обрабатывал такие вставленные символы?  
Не отвлекаясь от исходного примера, сделать преобразователь от исходной ссылки 
Код

<abzats>text text 
<link location="www.html">...</link> 
text text</abzats>

в стандартную html ссылку:
Код

<p>text text 
<a href="www.html">....</a> 
text text. </p>
 

То есть, мой вопрос скорее касается основ XML: 
можно ли обрабатывать команду непосредственно в том месте, где она находится в исходном тексте, вместо того чтобы вызывать ее специально? 
Я понимаю, это в какой-то мере противоречит самой идее XML, но неужели такой вариант не был предусмотрен при разработке XML стандарта? 

Я так понимаю, этого можно добиться двойной обработкой: 
1) создать промежуточный XML с заменой ссылок на нужный формат, 
2) преобразование промежуточного XML в html. 
А более естественных способов нет?  

Автор: Karabas 16.6.2006, 10:01
 smile Кто ищет тот (так иногда случается) всегда находит. 

Вот тут http://nwalsh.com/docs/tutorials/xsl/xsl/slides.html нашел пример обработки тэга в том месте где он появляется. 
Надо в исходном коде НЕ указывать аттрибутом match="" что ему обрабатывать: 
Код

<xsl:template match="doc">
  <html><head><title>A Document</title></head>
  <body><xsl:apply-templates/></body></html>
</xsl:template>

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

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

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


Пример использования: 
Код

<doc>
<para>This is a <emphasis>test</emphasis>.
<emphasis>Nested <emphasis>emphasis</emphasis></emphasis>.</para>
</doc>

 переходит в 
Код

<html>
<head>
<title>A Document</title>
</head>
<body>
<p>This is a <i>test</i>.
<i>Nested <b>emphasis</b></i>.</p>
</body>
</html>


Всем спасибо за помощь и сочувствие!  

Автор: Beard 16.6.2006, 10:08
Цитата(Karabas @  16.6.2006,  09:34 Найти цитируемый пост)
То есть, мой вопрос скорее касается основ XML: 
можно ли обрабатывать команду непосредственно в том месте, где она находится в исходном тексте, вместо того чтобы вызывать ее специально? 
Я понимаю, это в какой-то мере противоречит самой идее XML, но неужели такой вариант не был предусмотрен при разработке XML стандарта? 

Наверное, имелось ввиду XSL?


Цитата(Karabas @  16.6.2006,  09:34 Найти цитируемый пост)
Не отвлекаясь от исходного примера, сделать преобразователь от исходной ссылки 
    
<abzats>text text 
<link location="www.html">...</link> 
text text</abzats>


Код

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:template match="/">
      <xsl:copy>
         <xsl:apply-templates />
      </xsl:copy>
   </xsl:template>

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

   <xsl:template match="link">
      <a href="{@location}">
         <xsl:apply-templates />
      </a>
   </xsl:template>
</xsl:stylesheet>

Из кода становится ясно, как ...

Добавлено @ 10:08 
Опоздал smile 

Автор: Karabas 16.6.2006, 13:13
Спасибо, Beard!  

Автор: Porshen 15.5.2007, 05:08
Здравствуйте всем!
Эти сообщения мне очень помогли (что касается <xsl:copy-of select="child::node()" /> ), но достаточно скоро я столкнулся с почти таким же случаем, но вот с ним не смог разобраться. Вероятно не хватает знаний XPath... так вот...

имея вот такой XML (html разметка указана только для того, чтобы показать, в каких узлах она должна быть)
Код

<page>
  <title>Услуги</title>
  
  <about>
    <title>О компании</title>
    <description><p>Описание о компании. <span class="class1">Как мы тут работаем</span> и все прочее о нашей фирме</p></description>
  </about>

  <services>
    <service>
      <id>1</id>
      <name>Ремонт узлов механизмов и машин</name>
      <text><p>Ремонт узлов механизмов и машин можно заказать <a href="http://www.domain.com/">тут</a></p></text>
    </service>
    <service>
      <id>2</id>
      <name>Токарные, фрезерные и расточные работы</name>
      <text><p>Токарные, фрезерные и расточные работы лучше искать <a href="http://www.google.ru/">в Гугле</a> или в библиотеке</p></text>
    </service>
    <service>
      <id>3</id>
      <name>Изготовление чертежей</name>
      <text><p>Изготовление <strong>чертежей</strong> мы тоже делаем</p></text>
    </service>
  </services>
</page>

нам нужно сделать из него html страничку. Главное, как упоминал выше Karabas, вытащить из узлов именно текст с тегами!
Вот как я решил вопрос с вытаскиванием кода внутри узла description : в нужном месте вызвал заготовленный ранее шаблон
Код

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  
  <xsl:template match="/page">
    ...
    <xsl:apply-templates select="/page/about/description" />
    ...
  </xsl:template>

  <xsl:template match="/page/about/description" >
    <xsl:copy-of select="child::node()" />
  </xsl:template>

</xsl:stylesheet>

Вроде бы все хорошо и решение красивое, НО! Как быть когда надо вызвать шаблон внутри итерации <xsl:for-each>, когда надо применять шаблон к однотипным, но различным узлам с различным содержанием? Вот такая xsl таблица стилей несколько раз выведет содержимое узла text внутри узла service с id=1 (что, вобщем-то, логично и понятно)
Код

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  
  <xsl:template match="/page">
    ...
    <xsl:for-each select="/page/services/service">
      <xsl:apply-templates select="/page/services/service/text" />
    </xsl:for-each>
    ...
  </xsl:template>

  <xsl:template match="/page/services/service/text" >
    <xsl:copy-of select="child::node()" />
  </xsl:template>

</xsl:stylesheet>

пробовал вот так (сразу внутри итерации писать <xsl:copy-of>)
Код

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  
  <xsl:template match="/page">
    ...
    <xsl:for-each select="/page/services/service">
      <xsl:copy-of select="child::text" />
    </xsl:for-each>
    ...
  </xsl:template>

</xsl:stylesheet>

Но в этом случае у меня вытаскиваемый из узла html код обрамляется открывающим и закрывающим тегами <text>, то есть в месте вызова <xsl:copy-of> у меня лезет вот что
Код

<text><p>Ремонт узлов механизмов и машин можно заказать <a href="http://www.domain.com/">тут</a></p></text>

а надо чтоб было просто
Код

<p>Ремонт узлов механизмов и машин можно заказать <a href="http://www.domain.com/">тут</a></p>


Думаю надо как то адресовать содержимое <text> средствами XPath, но вот как ?? Или написать XSL похитрей. Подскажете???
 smile 

Автор: Golda 15.5.2007, 09:13
Просто используйте внутри for-each отновительный путь

Код

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template match="/page">
     <xsl:apply-templates select="/page/about/description" />
     <xsl:for-each select="services/service">
       <xsl:apply-templates select="text" />
     </xsl:for-each>
  </xsl:template>

  <xsl:template match="/page/about/description" >
    <xsl:copy-of select="child::node()" />
  </xsl:template>

  <xsl:template match="service/text" >
    <xsl:copy-of select="child::node()" />
  </xsl:template>
</xsl:stylesheet>

Автор: Porshen 15.5.2007, 12:33
 smile  сработало! Спасибо!

Автор: POLTER 9.8.2007, 15:42
Здравствуйте.
Аналогичная проблема возникла и у меня.
Но почему-то ни первый пример с CDATA, ни второй с child::node() не работают в FireFox и Opera, хотя в IE все отображается как надо.
Существует ли кроссбраузерное решение? (Преобразование link в a и т.п. не подходит, т.к. тегов может быть много).
Спасибо!

Автор: Golda 9.8.2007, 18:28
только что проверила. Вариант с child::node() работают одинаково успешно в IE 6.0, Firefox 2.0.0.4, Opera  9.21. Какие у вас версии броузеров и в чем отличие, что в каком броузере видите?

Автор: POLTER 9.8.2007, 22:06
Тестировал в IE6, 7; Opera 9.20; FireFox 2.0.03.
В IE все как положено - все html-теги выполняются.
А Опера и Лиса не распознают html-теги, т.е. выводят простой неформатированный текст.
Кстати, скопировал отсюда xml Porshen-a с вашим xsl-кодом -- результат тот же.

Автор: Beard 10.8.2007, 14:05
Цитата(POLTER @  9.8.2007,  15:42 Найти цитируемый пост)
Существует ли кроссбраузерное решение? (Преобразование link в a и т.п. не подходит, т.к. тегов может быть много).

В таком случае единственно правильное решение - генерировать HTML на стороне сервера
и отсылать клиенту, а не использовать встроенные процессоры браузеров, которые 
могут сильно отличаться. 

 
Цитата(POLTER @  9.8.2007,  22:06 Найти цитируемый пост)
А Опера и Лиса не распознают html-теги, т.е. выводят простой неформатированный текст.
Кстати, скопировал отсюда xml Porshen-a с вашим xsl-кодом -- результат тот же. 

Вроде для мозилл надо явно написать в скрипте:
Код

<xsl:output method="html"/>

Автор: POLTER 10.8.2007, 16:51
Цитата

Вроде для мозилл надо явно написать в скрипте <xsl:output method="html"/>

Спасибо большое, помогло! smile
Просто у меня стояло до этого xml, так как я вывожу xHTML, но оказывается работает и так.
Цитата

В таком случае единственно правильное решение - генерировать HTML на стороне сервера
и отсылать клиенту, а не использовать встроенные процессоры браузеров, которые 
могут сильно отличаться.

Ну теперь-то все работает кроссбраузерно smile
XSLT лучше в том плане, что не нужно разбираться с разными шаблонизаторами.

Автор: Exception 10.8.2007, 17:34
Тут не в output-method дело, а в том,что нормальные браузеры почему-то не догадались, что это XHTML-страница. Вероятнее всего, ты забыл проставить доктайпы и пространство имён XHTML:
Код
<xsl:output method="xml" indent="yes" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" />
<xsl:template match="/">
    <html xmlns=" http://www.w3 .org/1999/xhtml"> 
    </html>
</xsl:template>

Автор: POLTER 10.8.2007, 17:40
Нет, все это дело у меня стоит, выводится именно XHTML Strict, но без output method="html" не работало.

Автор: babycroc 15.1.2008, 13:31
Внимательно прочитал раздел и не смог найти ответ на свою проблему. Ни один из приведенных вариантов не прошел. Возможно другое решение. Дело в том, что уже есть готовый XML-документ на который я имею только ссылку и редактировать его не могу. http://..........t.xml?........  Необходима организация вывода данных из этого документа. Возможна ли такая реализация?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)