【问题标题】:Iterate ArrayList returned by Java extension function in XSLT(Saxon)迭代 XSLT(Saxon) 中 Java 扩展函数返回的 ArrayList
【发布时间】:2019-08-09 04:58:52
【问题描述】:

我有一个使用 XSLT 执行 XML 映射的程序。我为此使用 Saxon-HE-9.7 库。我还在 XSLT 中使用自反扩展函数。

XSLT 调用一个返回 ArrayList<HashMap<String, String>> 的 java 函数

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0" xmlns:SQLService="com.db.SQLService"  xmlns:ArrayList="java:java.util.ArrayList" xmlns:HashMap="java.util.HashMap" >
<xsl:output method="xml" indent="yes" />
<xsl:variable name="city">Texas</xsl:variable>
<xsl:variable name="query" select="'Select name, emp_id from employee where city = ?'" />
<xsl:variable name="list" select="SQLService:executeQueryMultiResult($query, $city)" />
<xsl:template match="/">
    <test>
        <xsl:for-each select="abc/company[@type='product']">
            <employee>
                <xsl:attribute name="details">
                    <xsl:value-of select="$list" />
                </xsl:attribute>
            </employee>
        </xsl:for-each>
    </test>
</xsl:template>
</xsl:stylesheet>   

我只得到列表中的单条记录,这是 executeQueryMultiResult 返回的列表的最后一条记录。

我想存储和迭代列表的所有元素?

【问题讨论】:

  • 试试
  • @AjeetSingh 试过了,没用。
  • HE是否支持反身扩展功能?我虽然它们仅在商业 PE 和 EE 版本中受支持。

标签: java xslt saxon


【解决方案1】:

首先,我有点惊讶的是,当您迭代 abc/company[@type='product'] 时,xsl:for-each 的主体不会以任何方式依赖于当前选定的 company。这意味着这个循环的每次迭代都会产生完全相同的输出。

在默认的Java-to-XPath转换下,ArrayList应该被转换成XPath序列,但是java Maps不会被转换成XPath maps;它们需要作为外部对象访问。

查看count($list) 返回的内容并检查它是否符合您的期望。

稍后

我无法重现该问题。我是这样测试的:

public void testListOfMaps() {
        try {
            Processor p = new Processor(true);

            XsltCompiler c = p.newXsltCompiler();
            String s = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                    "<xsl:stylesheet version=\"3.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"\n" +
                    "    xmlns:jf=\"java:s9apitest.TestReflexionHelper\">\n" +
                    "    <xsl:output method=\"text\" />\n" +
                    "    <xsl:template name='main'>\n" +
                    "        <xsl:variable name=\"theList\" select=\"jf:getListOfMaps('Weds', 'Wednesday')\" />\n" +
                    "        <xsl:value-of select=\"count($theList)\" />\n" +
                    "        <xsl:value-of select=\"Q{java:java.util.Map}get($theList[1], 'Weds')\" />\n" +
                    "    </xsl:template>\n" +
                    "</xsl:stylesheet>";
            XsltTransformer t = c.compile(new StreamSource(new StringReader(s))).load();
            StringWriter out = new StringWriter();
            Serializer ser = p.newSerializer(out);
            t.setDestination(ser);
            t.setInitialTemplate(new QName("main"));
            t.transform();
            assertTrue(out.toString().equals("2Wednesday"));
        } catch (SaxonApiException e1) {
            fail(e1.getMessage());
        }
    }

其中扩展函数 jf:getListOfMaps() 是:

public static List<Map<String, String>> getListOfMaps(String x, String y) {
        Map<String, String> m = new HashMap<>();
        m.put("Mon", "Monday");
        m.put("Tues", "Tuesday");
        m.put(x, y);
        Map<String, String> n = new HashMap<>();
        m.put("Jan", "January");
        m.put("Feb", "February");
        List<Map<String, String>> list = new ArrayList<>();
        list.add(m);
        list.add(n);
        return list;
    }

测试表明 Saxon 的行为符合规范:Java 映射列表被转换为外部对象的 XPath 序列,其中外部对象是 Java 映射的包装器,允许使用底层 Java 方法。

我在 Saxon 9.9 上运行此程序(不再支持 9.7)。

我建议您尝试生成一个简化问题的重现,方法是用任何人都可以运行以进行测试的相同签名的虚拟存根替换您的扩展函数。

我还建议您确切地告诉我们您的环境是什么。你说你用的是 Saxon-HE,我有点不解,因为 Saxon-HE 不支持自反扩展函数。

【讨论】:

  • count($list) 返回1,查询返回8条记录。
  • 感谢您的帮助。实际上,问题出在我的 ExtensionFunction 实现类上。我已经在单独的线程stackoverflow.com/questions/57474503/… 中重新发布了这个问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-16
  • 1970-01-01
  • 2012-06-25
  • 2021-06-02
  • 2015-07-12
  • 2012-04-30
  • 2015-06-17
相关资源
最近更新 更多