Эффективный конвейер XSLT с параметрами в Java - PullRequest
5 голосов
/ 19 августа 2010

В верхнем ответе на этот вопрос описан метод реализации эффективного конвейера XSLT в Java:

Эффективный конвейер XSLT в Java (или перенаправление результатов на источники)

К сожалению, хотя Transformer, похоже, предоставляет API для установки параметров XSLT, это, похоже, не имеет никакого эффекта. Например, у меня есть следующий код:

Transformer.java

import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.Templates;
import javax.xml.transform.sax.TransformerHandler; 
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.Transformer;
import java.io.File;
public class MyTransformer {
    public static void main(String[] args) throws javax.xml.transform.TransformerConfigurationException, javax.xml.transform.TransformerException{
        SAXTransformerFactory stf = (SAXTransformerFactory)TransformerFactory.newInstance();

        // These templates objects could be reused and obtained from elsewhere.
        Templates templates1 = stf.newTemplates(new StreamSource( new File("MyStylesheet1.xslt")));
        Templates templates2 = stf.newTemplates(new StreamSource(new File("MyStylesheet2.xslt")));

        TransformerHandler th1 = stf.newTransformerHandler(templates1);
        TransformerHandler th2 = stf.newTransformerHandler(templates2);

        th1.setResult(new SAXResult(th2));
        th2.setResult(new StreamResult(System.out));

        Transformer t = stf.newTransformer();

            //SETTING PARAMETERS HERE
        t.setParameter("foo","this is from param 1");
        t.setParameter("bar","this is from param 2");

        t.transform(new StreamSource(new File("in.xml")), new SAXResult(th1));

        // th1 feeds th2, which in turn feeds System.out.
    }
}

MyStylesheet1.xslt

<?xml version="1.0"?>
<stylesheet xmlns="http://www.w3.org/1999/XSL/Transform"  xmlns:foo="urn:foo" version="1.0">
    <output method="xml"/>

    <param name="foo"/>

    <template match="@*|node()">
        <copy>
            <apply-templates select="@*|node()"/>
        </copy>
    </template>

    <template match="foo:my/foo:hello">
        <copy>
            <foo:world>
                foo is : <value-of select="$foo"/>
            </foo:world>
        </copy>

    </template>
</stylesheet>

MyStylesheet2.xslt

<?xml version="1.0"?>
<stylesheet xmlns="http://www.w3.org/1999/XSL/Transform" xmlns:foo="urn:foo" version="1.0">
    <output method="xml"/>

    <param name="bar"/>

    <template match="@*|node()">
        <copy>
            <apply-templates select="@*|node()"/>
        </copy>
    </template>

    <template match="foo:my/foo:hello/foo:world">
        <copy>
            <apply-templates select="@*|node()"/>

            <attribute name="attr">
                <value-of select="$bar"/>
            </attribute>
        </copy>

    </template>
</stylesheet>

in.xml

<my xmlns="urn:foo">
    <hello/>
</my>

Что дает мне следующий вывод:

<?xml version="1.0" encoding="UTF-8"?><my xmlns="urn:foo">
        <hello><foo:world xmlns:foo="urn:foo">foo is : </foo:world></hello>
</my>

Как вы видите, foo: world / @ attr пусто, а текстовое содержимое foo: world говорит "foo is:". Ожидаемое поведение состоит в том, что они должны быть заполнены параметрами, переданными в метод setParameter.

Есть ли способ установить параметры XSL-преобразования, используя эту технику. Если нет, то может ли кто-нибудь порекомендовать альтернативный метод эффективного преобразования таблиц стилей в Java, чтобы также можно было установить параметры XSLT?

Ответы [ 2 ]

6 голосов
/ 19 августа 2010

Проблема в том, что каждый TransformerHandler имеет отдельный Transformer, связанный с ним. Есть проблема с вашим вторым шаблоном, но, как это пример, я думаю, это не имеет значения. Вы хотите:

//SETTING PARAMETERS HERE
th1.getTransformer().setParameter("foo","this is from param 1");
th2.getTransformer().setParameter("bar","this is from param 2");

Обратите внимание, что вам также не нужно создавать третий преобразователь, вы можете просто запустить цепочку преобразований в th1.getTransformer ()

0 голосов
/ 04 сентября 2013

относится к последней заметке. Вызов transform () для th1.getTransformer () с результатом, указывающим снова на th1, неверен. Это будет обработано дважды. использование нового Transformer (), как показано в первоначальном сообщении, является правильным способом.

t.transform(new StreamSource(new File("in.xml")), new SAXResult(th1));
...