Массивы с расширениями Java XSLT - PullRequest
2 голосов
/ 07 февраля 2011

Я пытаюсь использовать массивы в расширениях XSLT с использованием Java.

Я получаю следующую ошибку:

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.

1 Ответ

3 голосов
/ 08 февраля 2011

Я не думаю, что у вас может быть функция XPath, возвращающая массив строк. Однако вы можете создать расширение XPath XALAN, которое возвращает NodeSet. В вашем случае вам, вероятно, понадобится набор узлов, содержащий текстовые узлы. Затем все, что вам нужно сделать, это зациклить все узлы вашего набора узлов, чтобы получить все строки, которые вы сгенерировали в вашем наборе узлов расширения.
Я немного реорганизовал ваш пример, чтобы проиллюстрировать, как я считаю, решение, максимально приближенное к тому, что вы хотите, должно выглядеть. Первый класс - это ваше расширение. Как я уже сказал, он создает набор узлов, а не массив строк. Второй класс имеет 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

Опять же, как отмечали другие VIP-пользователи XSLT этого потока, это решение свяжет вас с Xalan Java версии 2.6 + ... Но правда в том, что:
1. XSLT 1.0 часто бесполезен без расширений.
2. у каждого процессора свой путь (javascript для MSXML, java для Xalan, объявленные точки входа для Xalan-C ...)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...