передача xml узлов / документов / фрагментов в качестве параметров в xslt - PullRequest
7 голосов
/ 24 сентября 2010

Я пытался передать w3c.dom.Document, Element и NodeList в качестве параметров для преобразования xslt.

Я хочу иметь возможность обрабатывать его в xslt:

<xsl:param name="links" />
<xsl:template match="/">
    <record>
        <xsl:for-each select="$links/*">
            <test />
        </xsl:for-each>
    </record>
</xsl:template>

Я передаю параметр как:

        Document params = createLinksParams(links);
        transformer.setParameter("links", params);

Я получаю это исключение:

'Неправильное преобразование из' com.sun.org.apache.xerces.internal.dom.DocumentImpl 'в' набор узлов '.'

Я пробовал также exslt:node-set(), xalan:nodeset() и т. Д., Но это не работает.

Кажется, что внутренне xalan исключает собственную реализацию Node.

Как я могу сделать нечто подобное, не сталкиваясь с этой проблемой?

Я не могу использовать document($param), потому что я создаю документ на лету.

Ответы [ 4 ]

4 голосов
/ 27 декабря 2012

Я нашел решение (здесь: XSLT-обработка с Java: передача содержимого XML в параметре ), которое также может работать для вашего случая:

String urls = "<urls><url id='google'>https://www.google.com</url>...";
trans.setParameter("lookupdoc", new StreamSource(new StringReader(urls)));

вместо создания uriresolverиз строки просто создайте источник потока из устройства чтения строк и передайте его в таблицу стилей.

После этого я смог нормально получить доступ к документу в формате XML:

<xsl:param name="lookupdoc"><urls/></xsl:param> 
... 
<xsl:variable name="googleurl" select="$lookupdoc/@id='google"/>

Не тестировал с xalan, но, возможно, ответ поможет другим, кто наткнулся на этот вопрос:)

4 голосов
/ 25 сентября 2010

(Отправка нового ответа, поскольку предыдущий не решил проблему, и этот новый радикально отличается от предыдущего)

Кажется, это известная проблема с процессором компиляции XALAN ( XALANJ-2057 , Как передать узел в качестве параметра для транслетов для XSLTC-процессора ).

Итак, каковы альтернативы?

  1. возиться с URI , как указано в ответ на Как мне пройти узел как параметр для транслетов для XSLTC Процессор Пост
  2. вместо Компилятор XALAN (XSLTC), использовать интерпретирующий процессор XALAN . Или любой другой процессор XSLT, который поддерживает такое поведение.
  3. Использовать DTMAxisIterator вместо этого также обрисовано в общих чертах в ответ на Как я могу передать узел как параметр для транслетов для XSLTC Процессор post - хотя и не уверен, будет ли он работать.
  4. Создайте новое дерево DOM , комбинируя ваш DOM "параметр" и исходный входной документ XSLT
1 голос
/ 08 ноября 2012

Вот рабочий пример с URIResolver Gambit, # 1 в списке решений:

import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.URIResolver;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import java.io.StringReader;
import java.io.StringWriter;

public class XSLTest {
    public static void main(String[] args) {

        class MyResolver implements URIResolver {
            String _xml;
            MyResolver(String xml) { _xml = xml; }
            @Override
            public Source resolve(String href, String base) throws TransformerException {
                return new StreamSource(new StringReader(_xml));
            }
        }

        String lookup =
            "<?xml version='1.0' encoding='utf-8'?>\n" +
            "<urls>\n" +
            "    <url id='google'>https://www.google.com</url>\n" +
            "    <url id='yahoo'>https://www.yahoo.com</url>\n" +
            "    <url id='apple'>https://www.apple.com</url>\n" +
            "</urls>";

        String main =
            "<?xml version='1.0' encoding='utf-8'?>" +
            "<list>"+
            "   <link ref='yahoo'>Yahoo</link>"+
            "   <link ref='google'>Google</link>"+
            "</list>";

        String xsl =
            "<?xml version='1.0' encoding='UTF-8'?>\n" +
            "<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>\n" +
            "    <xsl:param name='lookup-doc' />\n" +
            "    <xsl:variable name='lookup' select='document($lookup-doc)'/>\n" +
            "    <xsl:template match='/'>\n" +
            "        <xsl:for-each select='//link'>\n" +
            "            <xsl:variable name='ref' select='@ref'/>\n" +
            "            <xsl:element name='a'>\n" +
            "                <xsl:attribute name='href'>\n" +
            "                    <xsl:value-of select='$lookup//url[@id=$ref]'/>\n" +
            "                </xsl:attribute>\n" +
            "                <xsl:value-of select='text()'/>\n" +
            "            </xsl:element>\n" +
            "        </xsl:for-each>\n" +
            "    </xsl:template>\n" +
            "</xsl:stylesheet>";

        try {

            // xsl doc
            Source xsltSource = new StreamSource(new StringReader(xsl));

            TransformerFactory transFact = TransformerFactory.newInstance();
            Transformer trans = transFact.newTransformer(xsltSource);

            // main doc
            Source mainSource = new StreamSource(new StringReader(main));

            // lookup doc - stage it in the URI resolver
            trans.setURIResolver(new MyResolver(lookup));
            // dummy URL, you could use different values here to 
            // support multiple document parameters
            trans.setParameter("lookup-doc", "xml://lookup");

            StringWriter out = new StringWriter();
            trans.transform(mainSource, new StreamResult(out));

            System.out.println(out.toString());

        } catch (TransformerException e) {
            System.err.println("It's the wrong trousers Gromit, and they've gone wrong!");
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }

    }
}

У меня также была рабочая версия, где я поместил исходный код xml в URIкак

xml://<urls><url><url id='google'>https://www.google.com</url>...

но я подумал, что это может где-то ограничить длину.

0 голосов
/ 24 сентября 2010

Если вы посмотрите на документ JavaDoc , вы увидите, что он расширяет интерфейс Node , но не NodeList . Не уверен, что это сработает, но вы можете попробовать передать params.getChildNodes () вместо params .

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