Неожиданное поведение xsl:apply-templates/xsl:with-param с Xalan-J и saxon по сравнению с xsltproc
Я стараюсь изо всех сил, чтобы научиться использовать XSLT 1.0 из Java-кода, но постепенно начинаю постепенно сходить с ума.
У меня есть Xalan-J (оба xalan.jar и xsltc.jar со всеми jar-зависимостями), saxon и jing (последние два используются в моем проекте elswhere) в classpath, и я использую JAXP с комбинацией вызовов System.setProperty для принудительное использование реализаций классов, таких как TransformerFactory, как я хочу. Это также позволяет мне видеть поведение различных процессоров XSLT, используя один файл преобразования XSL, просто изменяя свойства из кода. Кроме того, я также использую xsltproc из среды cygwin, чтобы посмотреть, что он делает. Я также отлаживаю в Oxygen, чтобы убедиться, что мой Java-код не является проблемой.
Взгляните на этот фиктивный XSL:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:rng="http://relaxng.org/ns/structure/1.0"
xmlns:ex="http://example.com/ns/ex"
version="1.0">
<xsl:output method="xml" encoding="utf-8"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<!-- Start by finding the root grammar element -->
<xsl:apply-templates select="rng:grammar"/>
</xsl:template>
<xsl:template match="/rng:grammar">
<!-- Continue with child grammar elements -->
<xsl:apply-templates select="descendant::rng:grammar"/>
</xsl:template>
<xsl:template match="rng:grammar">
<!-- set the variable and pass it's value to another template -->
<xsl:variable name="parameter" select="'any-string-value'"/>
<xsl:message>initial value: <xsl:value-of select="$parameter"/></xsl:message>
<xsl:apply-templates select="descendant::ex:data">
<xsl:with-param name="parameter" select="$parameter"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="rng:optional">
<!-- use the param value here -->
<xsl:param name="parameter"/>
<xsl:message>final value: <xsl:value-of select="$parameter"/></xsl:message>
</xsl:template>
</xsl:stylesheet>
Он ничего не делает, кроме вызова некоторых шаблонов, которые работают с этим фиктивным экземпляром документа XML:
<?xml version="1.0" encoding="UTF-8"?>
<grammar
xmlns="http://relaxng.org/ns/structure/1.0"
xmlns:ex="http://example.com/ns/ex"
datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
<start>
<grammar ex:subgram="something" ns="http://example.com/ns/something">
<start>
<ex:data>
<optional />
</ex:data>
</start>
</grammar>
</start>
</grammar>
Я не знаю, что я делаю неправильно, но передача значения единственной переменной в этом XSL работает только с xsltc и xsltproc. И обычный ксалан, и саксон не могут передать значение. Смотрите результаты ниже.
xsltproc:
$ xsltproc transformation.xsl instance.xml
initial value: any-string-value
final value: any-string-value
Скомпилированный процессор Xalan (xsltc, а также с реализацией Java 1.6 по умолчанию):
Implementation: org.apache.xalan.xsltc.trax.TransformerFactoryImpl loaded from: ./lib/xalan-j_2_7_1/xsltc.jar
initial value: any-string-value
final value: any-string-value
Xalan Интерпретирующий процессор (xalan):
Implementation: org.apache.xalan.processor.TransformerFactoryImpl loaded from: ./lib/xalan-j_2_7_1/xalan.jar
initial value: any-string-value
final value:
саксонской:
Implementation: com.icl.saxon.TransformerFactoryImpl loaded from: ./lib/saxon6-5-5/saxon.jar
initial value: any-string-value
final value:
Мне нужно, чтобы это работало с xalan (причина - поддержка EXSLT). Я понятия не имею, что может быть причиной разных результатов. Я думал, что все эти процессоры реализуют XSLT 1.0, но я думаю, что они делают это по-другому. Является ли то, что я пытаюсь сделать в моем XSL, не совместимым с XSLT 1.0? Есть ли обходной путь, который я мог бы использовать, чтобы заставить это работать?
1 ответ
Объяснение простое:
<xsl:template match="rng:optional"> <!-- use the param value here --> <xsl:param name="parameter"/> <xsl:message>final value: <xsl:value-of select="$parameter"/></xsl:message> </xsl:template>
rng:optional
это ребенок ex:data
,
Там нет шаблона соответствия ex:data
поэтому он обрабатывается встроенным шаблоном XSLT для узла элемента.
Конечно, встроенный шаблон ничего не знает о передаваемых ему параметрах, поэтому он не передает их следующим применяемым шаблонам.
Таким образом, шаблон соответствует rng:optional
(выше) выбирается для выполнения встроенным шаблоном XSLT для элементов, и никакие параметры не передаются в этот выбранный шаблон.
Следовательно, значение parameter
param - пустая строка, и вы получаете правильный вывод как от Saxon, так и от XalanJ.