Wydajny rurociąg XSLT w Javie (lub przekierowywanie wyników do źródeł)

Mam serię arkuszy stylów XSL 2.0, które wprowadzają się do siebie, tj. wyjście arkusza stylów a feeds B feeds C.

Jaki jest najskuteczniejszy sposób na to? Pytanie przeformułowane brzmi: w jaki sposób można efektywnie kierować wyjście jednej transformacji w inną.

Oto moja pierwsza próba:

@Override
public void transform(Source data, Result out) throws TransformerException{
    for(Transformer autobot : autobots){
        if(autobots.indexOf(autobot) != (autobots.size()-1)){
            log.debug("Transforming prelim stylesheet...");
            data = transform(autobot,data);
        }else{
            log.debug("Transforming final stylesheet...");
            autobot.transform(data, out);
        }
    }
}

private Source transform(Transformer autobot, Source data) throws TransformerException{
    DOMResult result = new DOMResult();
    autobot.transform(data, result);
    Node node = result.getNode();
    return new DOMSource(node);
}

Jak widzisz, używam DOM, aby siedzieć pomiędzy transformacjami i chociaż jest to wygodne, to nie jest optymalna wydajność.

Czy jest jakaś łatwy sposób na wyznaczenie trasy, wyznaczenie trasy SAXResult do SAXSource? Innym rozwiązaniem byłoby rozwiązanie StAX.

Znam projekty takie jak XProc , co jest bardzo fajne, jeśli jeszcze nie zajrzałeś, ale nie chciałem inwestować w cały framework.

Author: Chris Scott, 2009-08-21

3 answers

Znalazłem to: # 3. Transformacje łańcuchowe, które pokazują dwa sposoby wykorzystania TransformerFactory do transformacji łańcuchowych, mając wyniki jednej transformacji karmić następną transformację, a następnie ostatecznie wyjście do systemu out. Pozwala to uniknąć konieczności pośredniej serializacji ciągów znaków, plików itp. pomiędzy transformacjami.

Gdy wiele, kolejne transformacje są wymagane do ten sam dokument XML, należy unikać niepotrzebne operacje parsowania. I często występują w kodzie, który przekształca ciąg znaków na inny ciąg znaków, następnie przekształca ten ciąg na jeszcze kolejny Sznurek. Nie tylko jest to powolne, ale może zużywać znaczne ilość pamięci, szczególnie jeśli ciągi pośrednie nie są wolno zbierać śmieci.

Większość przekształceń opiera się na cykl imprez saksofonowych. Parser saksofonu zazwyczaj analizuje strumień wejściowy lub kolejny InputSource do Sax events, które następnie można podać do Transformator. Zamiast mieć Wyjście transformatora do pliku, ciąg, lub inny taki wynik, SAXResult może być używany zamiast. SAXResult przyjmuje ContentHandler, który może przekazać te wydarzenia bezpośrednio do inny transformator itp.

Oto jedno podejście, a to, które ja zazwyczaj wolą, ponieważ zapewnia więcej elastyczność dla różnych wejść i źródła wyjściowe. To również sprawia, że dość łatwo stworzyć transformację łańcuch dynamicznie i ze zmienną liczba przekształceń.

SAXTransformerFactory stf = (SAXTransformerFactory)TransformerFactory.newInstance();

// These templates objects could be reused and obtained from elsewhere.
Templates templates1 = stf.newTemplates(new StreamSource(
  getClass().getResourceAsStream("MyStylesheet1.xslt")));
Templates templates2 = stf.newTemplates(new StreamSource(
  getClass().getResourceAsStream("MyStylesheet1.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();
t.transform(new StreamSource(System.in), new SAXResult(th1));

// th1 feeds th2, which in turn feeds System.out.
 23
Author: Mads Hansen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-01 18:24:18

Najlepiej trzymać się DOM tak, jak to robisz, ponieważ procesor XSLT i tak musiałby zbudować drzewo-strumieniowanie jest tylko opcją dla bardzo ograniczonej kategorii przekształceń, a kilka, jeśli jakiekolwiek procesory mogą to rozgryźć automatycznie i przełączyć się na implementację tylko do strumieniowania; w przeciwnym razie po prostu odczytają dane wejściowe i zbudują drzewo.

 2
Author: Pavel Minaev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-21 17:22:43

Powiązane pytanie wydajny rurociąg XSLT, z paramami, w Javie wyjaśnione na temat poprawnych parametrów przechodzących do takiego łańcucha transformatora.

I dał też wskazówkę na nieco krótsze rozwiązanie bez trzeciego transformatora:

SAXTransformerFactory stf = (SAXTransformerFactory)TransformerFactory.newInstance();

Templates templates1 = stf.newTemplates(new StreamSource(
        getClass().getResourceAsStream("MyStylesheet1.xslt")));
Templates templates2 = stf.newTemplates(new StreamSource(
        getClass().getResourceAsStream("MyStylesheet2.xslt")));

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

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

// Note that indent, etc should be applied to the last transformer in chain:
th2.getTransformer().setOutputProperty(OutputKeys.INDENT, "yes");

th1.getTransformer().transform(new StreamSource(System.in), new SAXResult(th2));
 2
Author: Vadzim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:46:38