I've got a fairly complex JAXB tree object. For every leaf node, I need to filter its actual value
E.g.
<Book>
<Title>Yogasana Vijnana: the Science of Yoga</Title>
<Author>Dhirendra Brahmachari</Author>
<Date>1966</Date>
</Book>
The leaf nodes here would be Title
,author
and Date
.
Imagine that I need a marshalled document for this JAXB model with the first character removed for every leaf node:
<Book>
<Title>ogasana Vijnana: the Science of Yoga</Title>
<Author>hirendra Brahmachari</Author>
<Date>966</Date>
</Book>
What is the best approach?
I see two starting points, however, I'm currently stuck.
1. Do the change in the JAXB model
Is there some traversal mechnism which I can use to get the leaf elements of any JAXB object (some kind of Visitor pattern or something)?
2. Hook into the marshalling
Maybe we can hook into marshalling, e.g. using a XMLStreamWriter
..
Is there an elegant solution for this kind of problem?
You could post-process the resulting XML
to remove the first character of the text content of each leaf nodes using XSLT
with the next stylesheet:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="*">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<!-- For each text content of leaf nodes (nodes without child nodes) -->
<xsl:template match="*[not(*)]/text()">
<!-- Skip the first character -->
<xsl:value-of select="substring(., 2)"/>
</xsl:template>
</xsl:stylesheet>
According to the size of your resulting XML
you could either keep the result into memory before applying the stylesheet or store first the resulting XML
into a temporary file.
Here is how your code could be assuming that the resulting XML
can fit into memory:
// Create the marshaller for the class Book
JAXBContext jaxbContext = JAXBContext.newInstance(Book.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
// Make the output being pretty printed
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
// Marshall the book instance and keep the result into a ByteArrayOutputStream
ByteArrayOutputStream out = new ByteArrayOutputStream();
jaxbMarshaller.marshal(book, out);
TransformerFactory factory = TransformerFactory.newInstance();
// Define the stylesheet to apply
Transformer transformer = factory.newTransformer(new StreamSource(xsltFile));
// Define the input XML content
Source text = new StreamSource(new ByteArrayInputStream(out.toByteArray()));
// Apply the stylesheet and store the content into outputFile
transformer.transform(text, new StreamResult(outputFile));
Output:
<?xml version="1.0" encoding="UTF-8"?>
<Book>
<Title>ogasana Vijnana: the Science of Yoga</Title>
<Author>hirendra Brahmachari</Author>
<Date>966</Date>
</Book>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With