2012-12-10 1 views
3

Надеюсь, кто-то может дать мне руку. Эта проблема уже несколько дней утомляет меня. Корень моей проблемы заключается в том, что я хочу добавить разметку ко всем узлам в порядке документов между двумя элементами.Код XSLT, необходимый для стилизации текста между двумя элементами

У меня есть документ, который имеет XML, похожее на это:

<Employees> 
    <Employee> 
    <Title>Mr.</Title> 
    <FirstName>John</FirstName> 
    <LastName>Doe</LastName> 
</Employee> 
    <Employee> 
    <Title>Mr.</Title> 
    <FirstName>Tom</FirstName> 
    <LastName>Doe</LastName> 
    </Employee> 
</Employees> 

Когда я использую функцию Oracle в «разметке», который помечает до поиска хитов, и я искать строку «John Doe», я получаю XML-результат выглядит следующим образом:

<Employees> 
    <Employee> 
    <Title>Mr.</Title> 
    <FirstName><hitStart/>John</FirstName> 
    <LastName>Doe<hitEnd/></LastName> 
    </Employee> 
    <Employee> 
    <Title>Mr.</Title> 
    <FirstName>Tom</FirstName> 
    <LastName>Doe</LastName> 
    </Employee> 
</Employees> 

Я хочу преобразовать это в XHTML, который выделяет хит. Например, следующий XHTML будет полезным результатом:

<TABLE> 
    <TR> 
    <TD>Mr. <b style="color:red">John Doe</b></TD> 
    <TR> 
    <TR> 
    <TD>Tom Doe</TD> 
    </TR> 
</TABLE> 

Я попытался написание таблиц стилей, которые используют применяемые-шаблоны или именованные шаблоны для навигации по документу, но я не могу заставить их работать. Использование шаблонов apply сложно, потому что я не могу передать параметр, указывающий, находятся ли узлы в элементах hitStart и hitEnd. Использование именованных шаблонов сложно, потому что мне нужно обрабатывать текстовые и элементные узлы по-разному, чего я не могу сделать в XSLT 1.0. Помощь была бы оценена.

Спасибо, Brian

Спасибо всем, кто помог !!!! Вы, ребята, здорово!

Вот что я остановился на:

<xsl:template match="/*|node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*"/> 
     <xsl:apply-templates select="node()[1]"/> 
    </xsl:copy> 
    <xsl:apply-templates select="following-sibling::node()[1]"/> 
</xsl:template> 
<xsl:template match="text()[preceding::*[self::hitStart or self::hitEnd][1][self::hitStart] 
and following::*[self::hitStart or self::hitEnd][1][self::hitEnd]]"> 
    <span style="color:red;font-style:italic;font-weight:bold"><xsl:value-of select="."/></span> 
    <xsl:apply-templates select="following-sibling::node()[1]"/> 
</xsl:template> 
<xsl:template match="hitStart|hitEnd"> 
    <xsl:apply-templates select="following-sibling::node()[1]"/> 
</xsl:template> 
+0

brianv, я полностью изменил ответ с помощью нового решения. Это лучше сейчас? :) –

+0

Отлично, Dimitre !! Огромное спасибо. Это сделал трюк. Поскольку мой реальный XML-атрибут имеет атрибуты, даже на корневом узле, я сделал несколько настроек.Вот что работает для меня: – brianv

+0

' ' – brianv

ответ

3

Это преобразование:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output omit-xml-declaration="yes" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

<xsl:template match="node()|@*"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()[1]"/> 
    </xsl:copy> 
    <xsl:apply-templates select="following-sibling::node()[1]"/> 
    </xsl:template> 

<xsl:template match= 
    "text() 
     [preceding::*[self::hitStart or self::hitEnd][1][self::hitStart] 
    and 
     following::*[self::hitStart or self::hitEnd][1][self::hitEnd] 
     ]"> 
    <xsl:value-of select="concat('*** ', ., ' ***')"/> 
    </xsl:template> 

<xsl:template match="hitStart|hitEnd"> 
    <xsl:apply-templates select="following-sibling::node()[1]"/> 
    </xsl:template> 
</xsl:stylesheet> 

при применении против предоставленного документа XML:

<Employees> 
    <Employee> 
    <Title>Mr.</Title> 
    <FirstName><hitStart/>John</FirstName> 
    <LastName>Doe<hitEnd/></LastName> 
    </Employee> 
    <Employee> 
    <Title>Mr.</Title> 
    <FirstName>Tom</FirstName> 
    <LastName>Doe</LastName> 
    </Employee> 
</Employees> 

высокие огни каждый текстовый узел в промежутке между элементами hitStart и hitEnd - окружив его тремя звездочками и производя разыскиваемого, правильный результат:

<Employees> 
    <Employee> 
     <Title>Mr.</Title> 
     <FirstName>*** John ***</FirstName> 
     <LastName>*** Doe ***</LastName> 
    </Employee> 
    <Employee> 
     <Title>Mr.</Title> 
     <FirstName>Tom</FirstName> 
     <LastName>Doe</LastName> 
    </Employee> 
</Employees> 

Объяснение:

Использование и наиважнейшая «мелкозернистого» правила идентичности.

+0

Спасибо, Димитр! Это приближает меня. Однако, когда ине являются братьями и сестрами, подобными примеру, то набор узлов не собирает узлы между ними. Я думаю, что это ответ, но у меня есть немного больше настроек. – brianv

+0

@brianv В этом случае используйте оси: 'follow ::' и 'previous ::' –

+0

Еще раз спасибо. Это делает трюк! Последняя проблема заключается в том, что я хочу запустить логику для всех пар hitTart/hitEnd. Другими словами, я не буду знать, сколько ординарных пар будет. Прямо сейчас, я изучаю, могу ли я использовать шаблоны приложений, чтобы поймать элемент hitStart, а затем в этом совпадении с шаблоном, я пытаюсь выяснить, могу ли я использовать position() для определения порядкового номера. Пока не повезло. Кстати, мне нравится, как вы использовали круглые скобки, чтобы найти все элементы hitStart и hitEnd, прежде чем определять позицию. Я не знал, что круглые скобки можно использовать так. Спасибо! – brianv

1

Это не идеальный, но вы могли бы сделать что-то быстро и грязно, как ...

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:output method="xml" encoding="utf-8" indent="no"/> 

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

    <xsl:template match="FirstName[hitStart]"> 
     <span class="alert"><xsl:value-of select="."/>&#160;</span> 
    </xsl:template> 
    <xsl:template match="FirstName"> 
     <xsl:value-of select="."/>&#160; 
    </xsl:template> 
    <xsl:template match="LastName[hitEnd]"> 
     <span class="alert"><xsl:value-of select="."/></span> 
    </xsl:template> 
    <xsl:template match="LastName"> 
     <xsl:value-of select="."/> 
    </xsl:template> 
    <xsl:template match="Employees/Employee"> 
     <tr> 
      <td> 
       <xsl:apply-templates select="Title"/> 
      </td> 
      <td> 
       <xsl:apply-templates select="FirstName | LastName"/> 
      </td> 
     </tr> 
    </xsl:template> 
</xsl:stylesheet> 
+0

Спасибо, Патрик. Это, похоже, работает для примера, но я должен был упомянуть, что у меня будет широкий выбор вариантов использования. Например, у меня может быть asdf Mary qwer Beth . Кроме того, элементы могут иметь любое имя. Нет определенного DTD. Я хочу добавить форматирование ко всему тексту между элементами hitStart и hitEnd и без форматирования для любого другого текста. Мне любопытно, почему ты использовал пробел? Я не так хорошо знаком с этим элементом HTML. Благодаря! – brianv

0

Простое решение, которое использует запретить маскирование для предотвращения ошибок запуска элемента без концовки, и заканчивая элемент без начальный элемент.

<?xml version="1.0"?> 
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="xhtml" indent="yes"/> 

    <xsl:template match="/Employees"> 
     <TABLE> 
      <xsl:apply-templates select="Employee"/> 
     </TABLE> 
    </xsl:template> 

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

    <xsl:template match="hitStart"> 
     <xsl:value-of disable-output-escaping="yes" select="'&lt;b style=&quot;color:red&quot;&gt;'"/> 
    </xsl:template> 

    <xsl:template match="hitEnd"> 
     <xsl:value-of disable-output-escaping="yes" select="'&lt;/b&gt;'"/> 
    </xsl:template> 
</xsl:transform> 
+0

Спасибо, Joepie! Я разработал решение от предложения Димитрия выше, поэтому я не уверен, что это сработало бы для меня.Раньше я не использовал disable-output-escaping, так что это интересная идея, о которой я подумаю. – brianv

+0

Как вы решили проблему смещения начального тега и конечного тега с помощью решения Dimitre? – Joep

+0

Joepie, я обновил решение выше в моем вопросе. Вчера вечером я понял, что оставил это. Сожалею. – brianv