【问题标题】:Arrays with java XSLT Extensions带有 java XSLT 扩展的数组
【发布时间】:2011-02-07 11:16:21
【问题描述】:

我正在尝试使用 java 在 XSLT 扩展中使用数组。

我收到以下错误:

Caused by: java.lang.ClassCastException: org.apache.xpath.objects.XObject 
                     cannot be cast to org.apache.xpath.objects.XNodeSet.

我使用数组的方式是。扩展类方法

public static String[] getEvents(String contractIdStr,String tradeIdStr) {
    return new String[]{"MacroType","Type","SubType"};
}

XSL 内部,

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:partyrefrule="com.converter.Rules" 
 exclude-result-prefixes="partyrefrule">

    <xsl:variable name="vLastNegoTradeEvents">
        <xsl:value-of select="partyrefrule:getEvents($cVal,$tVal)"/>
    </xsl:variable>

    <xsl:message terminate="no">
        <xsl:value-of select="$vLastNegoTradeEvents[0]"/>
    </xsl:message>
</xsl:stylesheet>

我正在为此使用 XALAN Parse。

【问题讨论】:

  • 我不知道答案:但请注意它是特定于产品的。适用于 Xalan 的东西可能不适用于另一个 XSLT 处理器,反之亦然。 XSLT 标准和 JAXP API 中都没有定义扩展函数的工作方式。
  • 我认为错误很明显:您不能扩展 XPath 函数和运算符数据类型。您可以在 XSLT 和 XPath 中使用扩展对象来保存和传递它们的值,但是对它们的任何操作都应该由扩展函数/元素实现来处理。
  • @Alejandro : 这可以与其他解析器一起使用!
  • 你是指其他 XSLT 处理器吗?

标签: java xslt


【解决方案1】:

我认为您不能让 XPath 函数返回字符串数组。但是,您可以创建一个返回 NodeSet 的 XPath XALAN 扩展。在您的情况下,您可能需要一个包含文本节点的节点集。然后,您所要做的就是在节点集的所有节点上循环,以检索您在扩展节点集中生成的所有字符串。
我已经对您的示例进行了一些重构,以说明我认为尽可能接近您想要的解决方案的解决方案。第一类是你的扩展。正如我所说,它创建了一个节点集而不是字符串数组。第二类有 XSL。这有点神秘,因为我需要在 java 中拥有所有东西(紧凑)才能使用 eclipse java 调试器(混合 eclipse XSLT 和 java 调试器是非入门者)。

所以你开始了:首先是扩展:

package com.converter;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;

import org.apache.xalan.extensions.ExpressionContext;
import org.apache.xpath.NodeSet;
import org.apache.xpath.objects.XNodeSet;
import org.apache.xpath.objects.XNodeSetForDOM;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

public class Rules {


    public static XNodeSet getEvents(ExpressionContext context, String s1, String s2) throws TransformerException {

        XNodeSet result = null ;

        try {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance() ;
            DocumentBuilder dBuilder;
            dBuilder = dbf.newDocumentBuilder();
            Document doc = dBuilder.newDocument();

            NodeSet ns = new NodeSet();

            ns.addNode( doc.createTextNode("MacroType" + s1 ) ) ;
            ns.addNode( doc.createTextNode("Type" + s2 ) ) ;
            ns.addNode( doc.createTextNode("SubType" + s1 + s2 ) ) ;

            result = new XNodeSetForDOM( (NodeList)ns, context.getXPathContext() );

        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        }
        return result ;
    }

}

然后是测试类(带有嵌入式 XSL)。

import java.io.StringReader;

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

public class Test {

    private static final String TESTXSL = "<?xml version=\"1.0\" encoding=\"UTF-8\"?> " +
        "<xsl:stylesheet version=\"1.0\"  " +
        " xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" " +
        " xmlns:partyrefrule=\"com.converter.Rules\" " +
        " exclude-result-prefixes=\"partyrefrule\"> " +
        "    <xsl:template match=\"/\"> " +
        "        <xsl:for-each select=\"partyrefrule:getEvents( 's1', 's2' )\"> " +
        "            <xsl:value-of select=\".\"/> " +
        "            <xsl:if test=\"position() != last()\">,</xsl:if> " +
        "        </xsl:for-each></xsl:template> " +
        "</xsl:stylesheet>" ;

    public static void main(String[] args) throws Exception {
        new Test().run () ;
    }

    public void run () throws Exception {
        TransformerFactory transFact = TransformerFactory.newInstance( );
        Source xsltSource = new StreamSource( new StringReader( TESTXSL ) );
        Transformer xsl = transFact.newTransformer(xsltSource);
        Source src = new DOMSource () ; // unused anyway
        Result result = new StreamResult( System.out ) ;
        xsl.transform(src , result );
    }

}

有了这两个类,输出是

<?xml version="1.0" encoding="UTF-8"?>MacroTypes1,Types2,SubTypes1s2

同样,正如该线程的其他 XSLT VIP 所指出的那样,此解决方案会将您绑定到 Xalan Java 2.6+ 版本...但事实是:
1. XSLT 1.0 在没有扩展的情况下通常是无用的。
2. 每个处理器都有自己的方式(MSXML 的 javascript,Xalan 的 java,Xalan-C 的声明入口点......)

【讨论】:

    猜你喜欢
    • 2021-11-25
    • 1970-01-01
    • 2020-08-03
    • 1970-01-01
    • 2011-03-04
    • 2019-06-16
    • 1970-01-01
    • 2011-01-28
    • 1970-01-01
    相关资源
    最近更新 更多