XSL:将作为参数传递的节点列表排序为模板

时间:2016-03-06 00:12:50

标签: sorting xslt parameter-passing

我面临一个奇怪的问题(恕我直言),简而言之就是:

作为参数传递给模板的节点列表无法排序。

以下是一个例子。

输入文件是:

<root>
    <a>BBB</a>
    <a>AAA</a>
</root>

转型是:

<xsl:stylesheet version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="xml" />

  <xsl:template match="/">
    <Root>
      <xsl:call-template name="processThis">
        <xsl:with-param name="nodeList" select="/*/a"/>
      </xsl:call-template>
    </Root>
  </xsl:template>

  <xsl:template name="processThis">
    <xsl:param name="nodeList" />

      <xsl:for-each select="$nodeList">
        <xsl:sort /><!-- ***** This causes the problem -->
        <xsl:variable name="thisVal" select="." />
        <result value="{$thisVal}" />
      </xsl:for-each>
    </xsl:template>

</xsl:stylesheet>

预期输出为:

<Root>
    <result value="AAA" />
    <result value="BBB" />
</Root>

但如果我进行转换,只需要一个空的&#39; Root&#39;生成元素,没有子节点。

如果我注释掉标有&#39; *****&#39;的行,则生成的Root元素确实包含子元素,但未排序(在这种情况下可以预期)。

如果我直接处理元素(而不是在传递列表的模板中作为参数处理),那么我可以使用&#39; sort&#39;,一切都按预期工作。这是&#39;直接&#39;转化:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" />

    <xsl:template match="/">
        <Root>
            <xsl:for-each select="/*/a">
                <xsl:sort />
                <xsl:variable name="thisVal" select="." />
                <result value="{$thisVal}" />
            </xsl:for-each>
        </Root>
    </xsl:template>

</xsl:stylesheet>

所以我的问题是:为什么没有一个列表作为参数传递给使用&#39;排序&#39;处理的模板。选项?

2016年3月7日更新:

XmlSpy和一些在线XSL处理器提供预期的(排序的)输出。

我已经尝试使用独立的Java程序,它给了我错误的结果。这是程序:

package my.test;

import java.io.File;
import java.io.StringWriter;

import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

public class Transform {

    public static void main(String[] args) throws Exception {
        String inputFileName = "Q:\\MiscThings\\t\\a.xml";
        String xslFileName = "Q:\\MiscThings\\t\\trans.xsl";

        Source xmlSource = new StreamSource(new File(inputFileName));
        Source xslSource = new StreamSource(new File(xslFileName));

        StringWriter stringWriter = new StringWriter();
        Result transformationResult = new StreamResult(stringWriter);

        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer(xslSource);
        transformer.transform(xmlSource, transformationResult);

        stringWriter.flush();
        String xmlResult = stringWriter.toString();

        System.out.println(xmlResult);
    }

}

1 个答案:

答案 0 :(得分:1)

我通过明确指定要使用的XSL处理器解决了这个问题。在我看来,我使用的JDK(我试过JRE7和JRE8)包含一个旧版本的XSL处理器,它不能正确处理文件。

我下载了Xalan 2.7.2并在&#39; xslt&#39;中指定了它的JAR。蚂蚁任务 - 并立即得到正确的结果。

我也尝试过saxon 9,并且得到了正确的结果。

我对现代JRE与有缺陷的XSL处理器打包这一事实感到惊讶。在我看来,我执行的转换并不复杂。