Как правильно использовать XSLT if-оператор? - PullRequest
3 голосов
/ 04 августа 2010

Я создал таблицу стилей XSLT, которая ищет узел и удаляет его. Это прекрасно работает. Теперь я хочу проверить, существует ли определенный узел, а затем удалить этот узел, если он там есть.

Поэтому я попытался добавить оператор if, и вот тут я столкнулся со следующей ошибкой:

Ошибка компиляции: строка файла dt.xls 10 элементов шаблона
шаблон элемента допускается только как дочерний элемент таблицы стилей

Я думаю, что понимаю ошибку, но не знаю, как ее обойти.

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

  <xsl:output omit-xml-declaration="yes" indent="yes"/>

  <xsl:template match="Ad">
    <xsl:template match="node()|@*">

      <xsl:if test="name-ad-size">
        <xsl:copy>
          <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
      </xsl:if>

    </xsl:template>
  </xsl:template>


  <xsl:template match="phy-ad-width"/>
  <xsl:strip-space elements="*"/>
  <xsl:preserve-space elements="codeListing sampleOutput"/>
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

1 Ответ

5 голосов
/ 04 августа 2010

Проблема, обычно, когда люди впервые пытаются использовать XSLT, заключается в том, что они думают, что это язык, как и любой другой, такой как C #, Java, PHP.Все эти языки используются, чтобы сообщать компьютеру, что делать.Но с XSLT все наоборот, вы сообщаете процессору, какой вывод вы ожидаете, основываясь на правилах.

Иногда использование xsl:if хорошо.Чаще всего это признак ошибки.Хитрость удаления узлов, элементов или текста заключается в создании соответствующего шаблона, который ничего не выводит.Примерно так:

<!-- starting point -->
<xsl:template match="/">
    <xsl:apply-templates select="root/something" />
</xsl:template>

<xsl:template match="name-ad-size">
   <!-- don't do anything, continue processing the rest of the document -->
   <xsl:apply-templates select="node() | @*" />
</xsl:template>

<!-- copy anything else -->
<xsl:template match="node() | @*">
   <xsl:copy>
      <xsl:apply-templates select="node() | @*" />
   </xsl:copy>
</xsl:template>

Почему это работает?Просто потому, что процессор проходит через каждый элемент и узел и сначала просматривает наиболее подходящий шаблон.Лучшее совпадение для узла <name-ad-size> - это совпадение, которое ничего не выводит, поэтому оно эффективно удаляет его.Другие узлы не совпадают, поэтому они попадают в шаблон «поймать все».

Примечание 1. Вероятно, полученная вами ошибка связана с тем, что вы по ошибке добавили <xsl:template> в другой элемент.Его можно разместить только под корнем <xsl:stylesheet> и нигде больше.

Примечание 2: порядок операторов <xsl:template> не имеет значения.Процессор будет использовать их все, чтобы найти наилучшее совпадение, независимо от того, где они находятся (если они находятся непосредственно под корнем).


РЕДАКТИРОВАТЬ: Кто-то волшебным образом получил ваш код.Вот история выше, примененная к вашей полной таблице стилей:

<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:preserve-space elements="codeListing sampleOutput"/>

  <!-- NOTE: it is better to have a starting point explicitly -->
  <xsl:template match="/">
    <xsl:apply-templates select="root/something" />
  </xsl:template>

  <!-- I assume now that you meant to delete the <Ad> elements -->
  <xsl:template match="Ad">
     <xsl:apply-templates select="node()|@*"/>
  </xsl:template>

  <!-- NOTE: here you were already deleting <phy-ad-width> and everything underneath it -->
  <xsl:template match="phy-ad-width"/>

  <!-- NOTE: copies everything that has no matching rule elsewhere -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...