XSLT соответствует пустым узлам - PullRequest
4 голосов
/ 06 сентября 2011

У меня есть XML-структура, подобная следующей:

<Root>
  <!-- ...other stuff -->
  <Events>
    <Event date="0000-00-00">Event Description etc...</Event>
    <Event date="0000-00-00">Event Description etc...</Event>
    <Event date="0000-00-00">Event Description etc...</Event>
  </Events>
  <!-- ...other stuff -->
</Root>

Тогда у меня есть XSLT в таблице стилей примерно так:

<xsl:variable name="Events" select="/Root/Events/Event" />

<xsl:template match="/">
  <!-- Stuff -->    
  <xsl:apply-templates select="$Events" />
  <!-- Stuff -->    
</xsl:template>

<xsl:template match="Event">
  <!-- Regular Event Template Transformation here -->
</xsl:template>    

<!-- ERROR HAPPENS HERE -->
<xsl:template match="not(node())">
  <p class="message">There are currently no upcoming events</p>
</xsl:template>

Что я хочу сделать, это иметь два шаблона,тот, который показывает только когда нет событий.Я ЗНАЮ, что могу использовать XSLT с <xsl:choose> и <xsl:when> тестами, чтобы подсчитать количество элементов и просто вызвать нужный шаблон, как я бы это делал на процедурных языках, но я пытаюсь научиться делать это с обработкой шаблонов.

Я получаю ошибку: Найден ожидаемый конец выражения '('. Not -> (<- node ()) </strong>

Ответы [ 4 ]

8 голосов
/ 07 сентября 2011

not(node()) не является допустимым шаблоном XSLT, попробуйте это:

<xsl:template match="Event">
  <!-- Regular Event Template Transformation here -->
</xsl:template>    

<xsl:template match="Events[not(Event)]">
  <p class="message">There are currently no upcoming events</p>
</xsl:template>
3 голосов
/ 06 сентября 2011

Это может работать лучше

<xsl:template match="*[not(node())]">
  <!-- ... -->

См. Также этот ответ здесь: XSLT Чтобы удалить пустые узлы и узлы с -1

2 голосов
/ 06 сентября 2011

Новый ответ

Внимательно прочитав ваш вопрос, я понимаю, что мои последние решения ни к чему вас не приведут.Мой новый ответ следующий:

Так как вам нужно знать, есть ли какие-либо элементы внутри Events, вам нужно изменить / соответствующий шаблон:

<xsl:template match="/">
   <!-- Stuff -->    
   <xsl:apply-templates select="/Root/Events" />
   <!-- Stuff -->    
</xsl:template>

Теперь шаблон, который соответствует толькозаполнить Events вместе с требуемым Event шаблоном:

<xsl:template="Events[count(child::Event) &gt; 0]">
   <xsl:apply-template select='./Event'/>
</xsl:template>

<xsl:template="Event">
    <!-- some stuff -->
</xsl:template>

Теперь шаблон, который соответствует пустому Events:

<xsl:template="Events[count(child::Event) = 0]">
   <p class="message">There are currently no upcoming events</p>
</xsl:template>

Старый ответ

Попробуйте с:

<!-- This matches every node with an empty string repr. Maybe you want
     to replace "self::*" to avoid attributes, etc." -->
<xsl:template match="*[string-length(self::*) = 0]">
</xsl:template>

Подробности:

Если я правильно помню, в XPath / XSL '*' соответствует любому типу узлов, т. Е. Текстовым узлам, узлам элементов, узлам комментариев,узлы атрибута и т. д. Таким образом, в данном контексте *[string-length(self::*) = 0] может совпадать с атрибутом;например, у вас может быть select='@*' где-то еще.Таким образом, этот шаблон может быть применен как к атрибутам, так и к элементам.

Если вы уверены, что он не будет соответствовать ни одному атрибуту, вы можете оставить его как есть.Однако мне нравится, что мой код выражает правильные идеи.Итак, если этот шаблон будет применяться только к элементам Event, я бы изменил соответствие на что-то вроде:

<xsl:template match="Event[string-length(self::*) = 0]">
</xsl:template>

Взглянув на спецификацию XSLT на http://www.w3.org/TR/xslt,, кажется, что * соответствуеттолько элементы.Однако я бы проверил это.

1 голос
/ 06 сентября 2011

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


Попробуйте выполнить преобразование (в котором хранится необходимая переменная):

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

    <xsl:variable name="Events" select="/Root/Events/Event"/>

    <xsl:template match="Root">
        <xsl:apply-templates select="$Events
            | Events[not(Event)]"/>  
    </xsl:template>

    <xsl:template match="Event">
        <p class="message">There is an event</p>
    </xsl:template>    

    <xsl:template match="Events">
        <p class="message">There are currently no upcoming events</p>
    </xsl:template>

</xsl:stylesheet>

При применении к вашему входу выдает:

<p class="message">There is an event</p>
<p class="message">There is an event</p>
<p class="message">There is an event</p>

При применении на входе без событий, таких как:

<Root>
  <Events/>
</Root>

производит:

<p class="message">There are currently no upcoming events</p>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...