Domanda

Ho una serie di fogli di stile XSL 2.0 che alimentano l'uno nell'altro, cioè l'uscita del foglio di stile A alimenta B alimenta C.

Qual è il modo più efficace di fare questo? La domanda è riformulato:. Come si può in modo efficiente l'uscita di una trasformazione in un altro

Ecco il mio primo tentativo:

@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);
}

Come si può vedere, sto usando un DOM di sedersi tra le trasformazioni, e anche se è conveniente, è non ottimale prestazioni saggio.

C'è un modo semplice per instradare a dire, percorso un SAXResult ad un SAXSource? Una soluzione StAX sarebbe un'altra opzione.

Sono consapevole di progetti come XProc , che è molto bello se non avete dato un'occhiata a ancora, ma non ho voglia di investire in un quadro complesso.

È stato utile?

Soluzione

Ho trovato questo: # 3. Concatenamento Trasformazioni che mostra due modi di utilizzare la TransformerFactory a trasformazioni catena, aventi i risultati di uno trasformano mangimi successivo trasformazione e infine uscita sistema fuori. Questo evita la necessità di una serializzazione intermedio String, file e così via tra le trasforma.

  

Quando multipla, successiva   trasformazioni sono necessari al   stesso documento XML, essere sicuri di evitare   le operazioni di analisi non necessarie. io   frequente imbattersi in codice che   trasforma una stringa in un'altra stringa,   poi trasforma la stringa ad ancora   un'altra stringa. Non solo questo è lento,   ma si può consumare un significativo   quantità di memoria, come pure, specialmente   Se le stringhe intermedi non sono   permesso di essere garbage collection.

     

La maggior parte delle trasformazioni si basano su un   serie di eventi SAX. Un parser SAX   tipicamente analizzare un InputStream o   un'altra InputSource in eventi SAX,   che possono poi essere alimentato ad un   Trasformatore. Invece di avere la   uscita del trasformatore in un file, String,   o un altro tale risultato, un SAXResult   può essere utilizzato. A SAXResult   accetta un ContentHandler, che può   passare questi eventi SAX direttamente al   un altro trasformatore, ecc.

     

Qui è un approccio, e quello che ho   di solito preferiscono in quanto fornisce più   flessibilità per vari input e   sorgenti di uscita. Inoltre lo rende   abbastanza facile creare una trasformazione   catena dinamicamente e con una variabile   numero di trasformazioni.

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.

Altri suggerimenti

La cosa migliore è quella di attenersi a DOM come si sta facendo, perché un processore XSLT avrebbe dovuto costruire un albero in ogni caso - lo streaming è solo un'opzione per la categoria molto limitata di trasformazioni, e pochi eventuali processori possono capirlo automaticamente e passare a un'implementazione di streaming sola; altrimenti basta leggere l'input e costruire l'albero.

pipeline efficiente a XSLT, con params, in Java chiarito su parametri corretti passaggio di tale catena trasformatore.

E ha anche dato un suggerimento su soluzione leggermente più corta senza terzo trasformatore:

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));
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top