Однако я выяснил, выглядит ли вход
как:
<dataset>
<title>My tile</title>
</dataset>
новый текстовый шаблон будет называться
Да, именно это и должен делать предоставленный код - я объясню это чуть позже.
Если вход выглядит так:
<dataset>
<title> </title>
</dataset>
новый текстовый шаблон никогда не будет
вызывается и вывод будет выглядеть как
<dataset>
<title/>
</dataset>
Я не мог воспроизвести это с Xalan (J или c) и многими другими процессорами XSLT У меня есть (Saxon 6.5.3, .NET XslCompiledTransform и XslTransform, Msxml3,4, 6, JD ,. .. так далее). Все они отображают сообщение об ошибке (внутри <xsl:message terminate="yes">
)
Единственный процессор XSLT, который выдает вышеуказанный вывод, - это AltovaXML (XmlSPY).
Если вы используете XmlSPY, возможно, вы могли бы попробовать либо использовать другой процессор XSLT, либо обратиться за помощью к Altova.
Теперь вернемся к первому поведению.
Объяснение
Предоставленный исходный XML-файл:
<dataset>
<title>My tile</title>
</dataset>
имеет три текстовых узла :
Первый текстовый узел находится между <dataset>
и <title>
и содержит только пробел.
Второй текстовый узел является единственным потомком <title>
, а его значением является строка «Моя плитка».
Третий и последний текстовый узел находится между </title>
и </dataset>
и состоит только из пробелов.
Когда шаблон, соответствующий text()
, выбран для обработки первого из трех вышеупомянутых текстовых узлов, тест считается положительным и выполняется <xsl:message terminate="yes">
- и это именно то поведение, о котором сообщается.
Решение
Существует простое решение. Просто измените шаблон, соответствующий text()
, чтобы он соответствовал только тем текстовым узлам, которые являются единственным текстовым узлом их родителя. Теперь преобразование XSLT ведет себя как и ожидалось для обоих типов документов XML, которые были изначально предоставлены :
<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="*">
<xsl:element name="{name(.)}" namespace="{namespace-uri(.)}">
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match=
"*[not(node()[2])]/text()
[normalize-space()='']">
<xsl:message terminate="yes">
<xsl:call-template name="output_message3_fail">
<xsl:with-param name="parent_node" select="name(..)"/>
</xsl:call-template>
</xsl:message>
</xsl:template>
<xsl:template name="output_message3_fail">
<xsl:param name="parent_node"/>
<xsl:message> ERROR:
<<xsl:copy-of select="$parent_node"/>> is empty
</xsl:message>
</xsl:template>
</xsl:stylesheet>
Когда это преобразование применяется к предоставленному документу XML:
<dataset>
<title>My tile</title>
</dataset>
Требуемый результат получен :
<dataset>
<title>My tile</title>
</dataset>
Когда он применяется ко второму документу XML :
<dataset>
<title> </title>
</dataset>
получен правильный результат:
ERROR:
<title> is empty