2010-07-29 4 views
62

Привет, я выполнил преобразование, которое бросает тег, если оно равно null.Почему XSLT выводит весь текст по умолчанию?

Я хотел проверить, работает ли мое преобразование нормально, поэтому вместо того, чтобы проверять его вручную, я написал еще один XSLT-код, который просто проверяет наличие этого конкретного тега в OUTPUT XML, если он равен нулю, а затем второй XSLT должен выводить текст «НАЙДЕН». (Я на самом деле не нужен XML вида продукции, но я только с помощью XSLT для поиска.)

Когда я попытался с этим кодом XSL ::

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="/SiebelMessage//SuppressCalendar[.!='']"> 
     FOUND 
    </xsl:template> 
</xsl:stylesheet> 

Он выводит все TEXT DATA, который в файле XML,

, чтобы избежать этого, я должен был написать этот код ::

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="/SiebelMessage//SuppressCalendar[.!='']"> 
     FOUND 
    </xsl:template> 
    <xsl:template match="text()"/> 
</xsl:stylesheet> 

почему бывший код выхода TEXT, почему я должен настоять XSL игнорировать все другой текст? заключается в том, что поведение всех парсеров XML или только моих собственных (я использую синтаксический анализатор msxml).

ответ

124

почему бывший код выхода TEXT, почему я настаиваю XSL игнорировать все другой текст? является то, что поведение всех парсеров XML или только моего собственного

Вы обнаруживаете один из самых основных функций XSLT, как указано в спецификации: в built-in templates of XSLT.

От the Spec:

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

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

Существует также встроенное правило шаблона для каждого режима, что позволяет рекурсивная обработки продолжать в том же режиме в отсутствие успешного соответствия шаблону шаблоном правило в таблице стилей. Этот шаблон правило применяется к обоим узлам элемента и корневого узла. Ниже показано эквивалент встроенного шаблона для режима m.

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

Существует также встроенное правило шаблона для текста и атрибуты узлов, копирует текст с помощью:

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

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

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

Встроенный шаблонное правило для узлов пространства имен также не делать ничего. Нет шаблона, который может соответствовать узлу пространства имен ; поэтому, правило шаблона является единственным правилом шаблона , которое применяется для пространства имен узлов.

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

Таким образом, сообщаемое поведение является результатом применения встроенных шаблонов - 1-го и 2-го из всех трех из них.

Это хороший шаблон дизайна XSLT переопределять встроенные шаблоны со своим собственным, который будет выдавать сообщение об ошибке, когда названных так, что программист сразу знает, что его преобразование является «утечка»:

Для пример, если этот XML-документ:

<a> 
    <b> 
    <c>Don't want to see this</c> 
    </b> 
</a> 

и обрабатывается с этим преобразованием:

<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="a|b"> 
    <xsl:copy> 
     <xsl:attribute name="name"> 
     <xsl:value-of select="name()"/> 
     </xsl:attribute> 
     <xsl:apply-templates/> 
    </xsl:copy> 
</xsl:template> 
</xsl:stylesheet> 

результат:

<a name="a"> 
    <b name="b">Don't want to see this</b> 
</a> 

и программист будет очень смущен, как нежелательный текст появился.

Однако, просто добавив этот catch-all template помогает избежать подобной путаницы и отлавливать ошибки сразу:

<xsl:template match="*"> 
    <xsl:message terminate="no"> 
    WARNING: Unmatched element: <xsl:value-of select="name()"/> 
    </xsl:message> 

    <xsl:apply-templates/> 
</xsl:template> 

Теперь, помимо запутанной выход программист получает предупреждение, что объясняет проблему немедленно:

WARNING: Unmatched element: c 
+4

+1: Отличное объяснение - гораздо более полное, чем принятый ответ, хотя принятый ответ также отвечает на конкретный вопрос. –

+0

@donroby: Спасибо. Почему мой ответ не будет затрагивать вопрос и отвечать на него? Любой, кто имеет эту проблему и читает мой ответ, поймет причину своей проблемы и сможет ее исправить. –

+0

@donroby: Мой ответ дает точный ответ: «Итак, сообщаемое поведение является результатом применения встроенных шаблонов - 2 из всех трех из них» ' –

12

Есть несколько built in template rules в XSL, один из которых заключается в следующем:

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

Он выводит текст.

+0

спасибо, так оно специфично для конкретного парсера или вообще? –

+0

Я думаю, его общее правило для всех парсеров сводится к его спецификации w3c. хорошо, спасибо :) –

+1

@infant programmer - он в спецификации, как вы уже отметили ...все синтаксические анализаторы XSL должны реализовать их. – Oded

Смежные вопросы