我正在尝试使用 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。
最佳答案
我认为 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 声明入口点...)
关于java - 具有 java XSLT 扩展的数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4920633/