Неожиданное поведение xsl: apply-templates / xsl: with-param с Xalan-J и saxon по сравнению с xsltproc - PullRequest
2 голосов
/ 09 февраля 2012

Я стараюсь изо всех сил, чтобы научиться использовать XSLT 1.0 из Java-кода, но постепенно начинаю постепенно сходить с ума.

У меня есть Xalan-J (оба xalan.jar иxsltc.jar со всеми jar-зависимостями), saxon и jing (последние два используются elswhere в моем проекте) на моем пути к классам, и я использую 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.И обычный xalan, и saxon не могут передать значение.См. Результаты ниже.

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 Ответ

2 голосов
/ 09 февраля 2012

Объяснение простое:

  <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 является пустой строкой, и вы получаете правильный вывод как от Saxon, так и от XalanJ.

...