передача XML-узлов / документов / фрагментов в качестве параметров xslt
Я пытался передать 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);
Я получаю это исключение:
'от 'ком.солнце.орг."Апач".xerces.внутренние.дом.DocumentImpl " на " узел-сеть.'
я тоже пытался exslt:node-set()
, xalan:nodeset()
etc, но это не работает.
это кажется, что внутренне xalan исключает свою собственную реализацию узла.
как я могу сделать что-то подобное без возникновения этой проблемы?
Я не могу использовать document($param)
потому что я строю doc на лету.
4 ответов
(публикация нового ответа, так как предыдущий не решил проблему, и этот новый радикально отличается от предыдущего)
кажется, известная проблема с процессором компиляции XALAN (XALANJ-2057, как я могу передать узел в качестве параметра транслетам для процессора XSLTC).
Итак, каковы альтернативы?
- возиться с URIs как указано в ответ как я могу передать узла в качестве параметра translets для XSLTC Процессор в должности
- вместо Процессор компиляции XALAN (XSLTC), использовать интерпретирующий процессор XALAN. Или любой другой процессор XSLT, поддерживающий такое поведение.
- Использовать DTMAxisIterator вместо этого также изложено в ответе на как я могу передать узла в качестве параметра translets для XSLTC Процессор post - не уверен, что он будет работать, хотя.
- создать новое дерево DOM, объединяя ваш" параметр " DOM и исходный входной документ XSLT
Я нашел решение (здесь: обработка XSLT с помощью Java: передача содержимого xml в параметре), который может работать для вашего случая:
String urls = "<urls><url id='google'>https://www.google.com</url>...";
trans.setParameter("lookupdoc", new StreamSource(new StringReader(urls)));
вместо создания uriresolver из строки просто создайте источник потока из считывателя строк и передайте его в таблицу стилей.
после этого я смог получить доступ к doc обычно как XML:
<xsl:param name="lookupdoc"><urls/></xsl:param>
...
<xsl:variable name="googleurl" select="$lookupdoc/@id='google"/>
не тестировал с xalan, но, возможно, ответ поможет другим, кто наткнется на это вопрос :)
Если вы посмотрите на Документ JavaDoc, вы можете видеть, что он расширяется узел интерфейс, но не узла. Не уверен, что это сработает, но вы можете попробовать пройти в params.getChildNodes() вместо params.
вот рабочий пример с Гамбитом URIResolver, #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>...
но я подумал, что это может где-то столкнуться с ограничениями длины.