【问题标题】:How to execute XSLT 2.0 with ant?如何用 ant 执行 XSLT 2.0?
【发布时间】:2009-05-28 07:53:03
【问题描述】:

我正在尝试从 ant 文件运行 XSLT 转换。

我正在使用带有 saxon 9 解析器的 XSLT 2.0 样式表(支持 XSLT 2.0)。

问题在于,ant 似乎总是调用 XSLT 1.0 解析器。

这是我的 ant 文件:

<xslt style="stylesheet.xslt"
   basedir="core/"    
   extension=".xml"
   destdir="core/"
   classpath="D:\\DevTools\\saxon\\bin\\saxon9.jar">
</xslt>

如果我直接调用它(没有 ant),它就可以工作。

有什么想法吗?

【问题讨论】:

标签: xslt ant saxon


【解决方案1】:

问题在于,虽然将 Saxon 添加到类路径中,但用于确定使用哪个 TransformerFactory 的默认 JAXP 机制将使用默认值 Xalan。您需要:

  • javax.xml.transform.TransformerFactory系统变量设置为net.sf.saxon.TransformerFactoryImpl
  • 将 saxon9.jar 添加到 CLASSPATH 系统变量中,或者
  • xslt 元素内使用&lt;factory name="net.sf.saxon.TransformerFactoryImpl"/&gt;

【讨论】:

    【解决方案2】:

    如果您遇到此问题,请检查您使用的不是 Ant 1.8.1,因为 Ant 1.8.1 中有一个 bug 会阻止此操作。 (虽然这不是原帖中的问题,因为那是在 Ant 1.8.1 发布之前)。

    您的选择是:

    1. 使用没有错误的 Ant 版本(例如 Ant 1.7.1)。
    2. 在 Ant 启动之前,将 CLASSPATH 中的 saxon9.jar 显式指定给 Ant,方法是:
      • 设置系统CLASSPATH环境变量,或者
      • -lib 命令行选项用于ant
    3. 使用 SAXON Ant 定义您自己的任务(如本线程的另一个答案所述)。
    4. 解决方法是将processor="org.apache.tools.ant.taskdefs.optional.TraXLiaison" 添加为xslt 任务元素的属性。

    我建议使用选项 1,然后使用选项 4。

    选项 2 会起作用,但它让运行 ant 的人负责设置他们的环境并正确运行 ant。我假设您不希望这样,这就是您尝试使 xslt 任务上的 classpath 属性工作的原因。

    选项 3 有限制,因为 SAXON Ant 需要下载并安装其 JAR 文件。此外,SAXON Ant 不适用于 SAXON 9.2 或更高版本(并且 SAXON Ant 自 2008 年 6 月创建以来一直没有更新)。

    理论上,指定factory 子元素会使您要使用的 XSLT 处理器显式化——以防止类加载器在其搜索的早期找到不同的 XSLT 处理器,并使用它代替您的 XSLT 处理器,后者是在 CLASSPATH 中进一步向下。在实践中(至少在 ant 1.7.0、1.7.1 和 1.8.0 中)如果指定了 factory 子元素,xslt 任务将忽略 classpath 属性——这意味着您必须求助于显式指定类路径(选项 2)。所以它无助于解决原来的问题。不过,这似乎已在 Ant 源代码中修复,因此可以在 1.8.1 之后的版本中使用。

    【讨论】:

    【解决方案3】:

    本教程似乎逐步说明了如何按照您的要求进行操作:

    http://www.abbeyworkshop.com/howto/xslt/ant-saxon/index.html

    从中看来,您正在做正确的事情。您确定需要双反斜杠吗?

    更新:xslt Ant 文档提到了“工厂”属性,这可能会帮助您更接近:

    http://ant.apache.org/manual/Tasks/style.html

    【讨论】:

      【解决方案4】:

      编辑: Dr. Michael Kay 指出 AntTransform 不再受支持,也不推荐。

      从撒克逊AntTransform class创建一个taskdef:

        <taskdef name="saxon-xslt" classname="net.sf.saxon.ant.AntTransform" classpath="${basedir}/lib/saxon/saxon9.jar;${basedir}/lib/saxon/saxon9-ant.jar"/>
      
         <saxon-xslt
           in="${source.xml}"
           out="${out.dir}/${output.xml}"
           style="${basedir}/${stylesheet.xsl}"
           force="true">
         </saxon-xslt>
      


      我已经开始使用标准的&lt;xslt&gt; 任务和&lt;classpath&gt; 中指定的saxon jar,但是遇到了性能问题。调用任务时,它似乎“挂起”了一段时间。我发现添加processor="trax" 并指定&lt;factory name="net.sf.saxon.TransformerFactoryImpl"/&gt; 有助于它运行得更快。

       <xslt in="${source.xml}"
             out="${out.dir}/${output.xml}"
             style="${basedir}/${stylesheet.xsl}"
             processor="trax">
             <factory name="net.sf.saxon.TransformerFactoryImpl"/>
             <classpath refid="saxon-classpath" />
       </xslt>  
      

      【讨论】:

      • 请注意,不再推荐使用 AntTransform 任务。事实证明它有问题,并且没有可行的策略来正确测试它,因为 Apache 没有为 Ant 发布一个全面的测试套件。
      • 注明。我已经开始使用标准的&lt;xslt&gt; 任务和&lt;classpath&gt; 中指定的saxon jar,但是遇到了性能问题。调用任务时,它似乎“挂起”了一段时间。最近,我发现添加processor="trax" 并指定&lt;factory name="net.sf.saxon.TransformerFactoryImpl"/&gt; 有助于它运行得更快。
      【解决方案5】:

      与其等待这个问题在 1.8.2 中得到修复,然后等待所有人最终升级到 1.8.2,不如推出自己的 XSLT 宏(适用于明确希望使用 Saxon 而不是用户的情况选定的 XSLT 引擎)

      <macrodef name="xslt" uri="com.mycompany.mydepartment">
          <attribute name="in" />
          <attribute name="out" />
          <attribute name="style" />
          <attribute name="classpath" default="${saxon.jar.path}" />
          <attribute name="taskname" default="mydep:xslt" />
          <element name="params" optional="true" implicit="true" />
          <sequential>
              <java classname="net.sf.saxon.Transform"
                    classpath="@{classpath}"
                    taskname="@{taskname}">
                  <classpath path="${saxon.jar.path}" />
                  <arg value="-s:@{in}" />
                  <arg value="-xsl:@{style}" />
                  <arg value="-o:@{out}" />
                  <params />
              </java>
          </sequential>
      </macrodef>
      

      然后您可以像这样调用它(假设在项目元素上设置了 xmlns:mydep="com.mycompany.mydepartment")

      <mydep:xslt in="${myinput}"
                   out="${myoutput}"
                   style="${myxslt}">
          <arg value="param1=value1" />
          <arg value="param2=value2" />
          <arg value="+param3=somefile.xml" />
      </mydep:xslt>
      

      您可以在 http://www.saxonica.com/documentation/using-xsl/commandline.xml 找到将参数传递给 Saxon 的文档

      【讨论】:

        【解决方案6】:

        至少在ant 1.8.0中,指定classpath的xslt任务非常慢。 问题似乎是类路径加载。我在 JDB 下运行 ant,它把所有额外的时间都花在了 org.apache.tools.ant.AntClassLoader.loadClass 读取 zip 文件上。

        我在运行 ant 之前尝试过这个,它运行得更快:

        ant -lib /path/to/saxon/saxon9.jar

        来自 Tom Howard 的 macrodef 效果更好,虽然它的 XSLT 参数语法很奇怪,但至少它是可能的。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-05-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-12-02
          • 1970-01-01
          相关资源
          最近更新 更多