XSLT apply-template with mode - неверный результат без соответствующего режима - PullRequest
5 голосов
/ 26 августа 2010

Вот простой случай.

Вот мой XML:

<?xml version="1.0" encoding="utf-8" ?>
<dogs>
    <dog type="Labrador">
        <Name>Doggy</Name>
    </dog>
    <dog type="Batard">
        <Name>Unknown</Name>
    </dog>
</dogs>

Этот XML используется с двумя Xslt. Это обычный:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
    <xsl:output method="text"/>

    <xsl:template match="dogs">
        <xsl:text>First template&#13;&#10;</xsl:text>
        <xsl:apply-templates select="." mode="othertemplate" />
    </xsl:template>
</xsl:stylesheet>

Это ребенок:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
    <xsl:include href="transform.xslt"/>

    <xsl:template match="dogs" mode="othertemplate">
        <xsl:text>&#9;&#9;Other template</xsl:text>
    </xsl:template>
</xsl:stylesheet>

Ребенок включает в себя общий (называемый transform.xslt).

Когда я выполняю ребенка, я получаю ожидаемый результат:

First template
        Other template

Когда я выполняю общий, я получаю странные результаты:

First template


        Doggy


        Unknown

Общий шаблон применяет шаблон с режимом "othertemplate". Этот режим включен, иногда, в дочерний xslt.

Я хочу, чтобы, если нет шаблона с режимом "othertemplate", то ничего выводить не нужно.

Я не хочу включать шаблон с режимом "othertemplate" с пустым телом для всех файлов xslt, которые не должны использовать этот режим шаблона ...

Что мне делать?

Спасибо

Ответы [ 2 ]

10 голосов
/ 26 августа 2010

Встроенные правила шаблонов в XSLT

Содержимое элемента и дополнительный пробел появляются из-за встроенных правил шаблонов XSLT, также известных как шаблоны по умолчанию.Эти правила применяются, когда нет другого соответствующего шаблона.Встроенные правила шаблона:

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

<xsl:template match="text()|@*">
  <xsl:value-of select="."/>
</xsl:template>

<xsl:template match="processing-instruction()|comment()"/>

Встроенные правила шаблона рекурсивно обрабатывают корневые и элементные узлы и копируют текст (и значения атрибутов, если выбраны узлы атрибутов).Встроенное шаблонное правило для обработки инструкций и комментариев - ничего не делать.Узлы пространства имен не обрабатываются по умолчанию.Обратите внимание, что <xsl:apply-templates/> является практически сокращением для <xsl:apply-templates select="child::node()"/>, поэтому он не будет выбирать узлы атрибута или пространства имен.

Существует также встроенное правило шаблона для каждого режима.Эти шаблоны похожи на шаблоны по умолчанию для элементов и root, за исключением того, что они продолжают обрабатываться в том же режиме.

<xsl:template match="*|/" mode="foobar">
  <xsl:apply-templates mode="foobar"/>
</xsl:template>

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

Предупреждение о бесконечных циклах из-за <xsl:apply-templates select="."/>

Обычно apply-templates используется для обработки потомков.В вашем примере кода вы выбрали текущий узел при вызове apply-templates.Это может привести к бесконечному циклу, если сам шаблон применяется из-за команды apply-templates внутри него.Пример ниже

<xsl:template match="foobar">
  <!-- This is an infinite loop -->
  <xsl:apply-templates select="."/>
</xsl:template>

Кстати.По общему правилу объединения таблиц стилей тщательно продумайте, какой шаблон следует использовать, а какой - импортировать или включить.(У меня прочитано , что, как правило, Майкл Кей, кажется, рекомендует использовать <xsl:import> для импорта таблицы стилей общего случая в таблицу стилей специального случая, а не наоборот.)

6 голосов
/ 26 августа 2010

Встроенные шаблоны XSLT определены и выбраны для каждого режима .Итак, встроенный шаблон для текстовых узлов выбран и (по определению) выводит текстовый узел.

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

<xsl:template match="text()" mode="othertemplate"/>

Включите вышеперечисленное в импортированную таблицу стилей .

...