Saxon in Java: XSLT Code Reuse

KayT

New Member
As a continuation in my thought patterns from this question: Saxon in Java: XSLT for CSV to XMLPer Michael Kay's answer on that question, I eventually ended up with the following code for applying an XSLT to a document:\[code\]Processor processor = new Processor(false);StringWriter stringWriter = new StringWriter();Serializer serializer = new Serializer(stringWriter);XsltCompiler compiler = processor.newXsltCompiler();XsltExecutable executable = compiler.compile(new StreamSource(new File(transformLocation)));XsltTransformer transformer = executable.load();transformer.setInitialTemplate(new QName("main"));transformer.setParameter(new QName("filePath"), new XdmAtomicValue("location/of/Test.csv"));transformer.setDestination(serializer);transformer.transform();String transformedDocument = stringWriter.toString().trim();\[/code\]This code makes use of the s9api in Saxon (I'm on version 9.4 HE). It allows me to set the initial template and dynamically inject the path to the document to be transformed, which allows me to transform non-XML files (such as CSV, in this particular case).However, this somewhat obliterates my code-re-usability.Let me explain: I have a \[code\]transformDocument()\[/code\] method. Originally, before I was trying to do crazy things like transform CSV and was working only with XML, it was called by both my \[code\]marshalObjectToDocument()\[/code\] and \[code\]unmarshalDocumentToObject()\[/code\] methods (there's the re-usability).Here's a comparison of the two directions given a world of only XML:[*]\[code\]unmarshalDocumentToObject()\[/code\]
  • I start with a file that has the document inside of it.
  • I do this: \[code\]new StreamSource(new File(documentLocation))\[/code\]
  • This \[code\]StreamSource\[/code\] can be passed to \[code\]transformDocument\[/code\] as the "source" (\[code\]XsltTransformer.setSource()\[/code\]).
[*]\[code\]marshalObjectToDocument()\[/code\]
  • I start with on object of some sort.
  • This gets marshaled into a giant String of the XML.
  • I do this: \[code\]new StreamSource(new StringReader(giantStringOfXML))\[/code\]
  • This \[code\]StreamSource\[/code\] can be passed to \[code\]transformDocument\[/code\] as the "source" (\[code\]XsltTransformer.setSource()\[/code\]).
In case 1 (\[code\]unmarshalDocumentToObject()\[/code\]) I have a file path coming in, so I could just change \[code\]transformDocument()\[/code\] to take a file path String and pass it that so it can manually inject it into the XSLT parameter. This would work for both XML and plain text.In case 2 (\[code\]marshalObjectToDocument()\[/code\]) I have NO file path. I have an object, which gets converted to a giant String containing its XML representation. I can't pass a file path String to \[code\]transformDocument()\[/code\] because I don't have a file. Now I can't use \[code\]transformDocument()\[/code\]. Code re-usability destroyed.My goal in all of this is both to be able to somehow treat both XML and plain text documents the same way in the code and to be able to re-use my code for applying XSLTs and XSDs whether I'm marshaling or unmarshaling. Is this a quixotic goal? Am I doomed to be relegated to writing different code for each document type and direction? Or can someone see a way around this?
 
Back
Top