unmarshal parse online jaxbunmarshaller bean java xml jaxb marshalling

java - parse - Clasificación JAXB: valores de filtro de elementos de hoja



parse xml java jaxb (2)

Podría postprocesar el XML resultante para eliminar el primer carácter del contenido de texto de cada nodo de hoja mediante XSLT con la siguiente hoja de estilo:

<?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>

De acuerdo con el tamaño de su XML resultante, puede mantener el resultado en la memoria antes de aplicar la hoja de estilo o almacenar primero el XML resultante en un archivo temporal.

Aquí es cómo su código podría estar asumiendo que el XML resultante puede caber en la memoria:

// 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));

Salida:

<?xml version="1.0" encoding="UTF-8"?> <Book> <Title>ogasana Vijnana: the Science of Yoga</Title> <Author>hirendra Brahmachari</Author> <Date>966</Date> </Book>

Tengo un objeto de árbol JAXB bastante complejo. Para cada nodo de hoja , necesito filtrar su valor real

P.ej

<Book> <Title>Yogasana Vijnana: the Science of Yoga</Title> <Author>Dhirendra Brahmachari</Author> <Date>1966</Date> </Book>

Los nodos de hoja aquí serían Title , author y Date .
Imagine que necesito un documento estructurado para este modelo JAXB con el primer carácter eliminado para cada nodo hoja:

<Book> <Title>ogasana Vijnana: the Science of Yoga</Title> <Author>hirendra Brahmachari</Author> <Date>966</Date> </Book>


¿Cuál es el mejor enfoque?
Veo dos puntos de partida, sin embargo, actualmente estoy estancado.

1. Hacer el cambio en el modelo JAXB
¿Hay algún mecanismo transversal que pueda usar para obtener los elementos de hoja de cualquier objeto JAXB (algún tipo de patrón de visitante o algo así)?

2. Enganche en la clasificación
Quizás podamos engancharnos en el marshalling, por ejemplo, usando un XMLStreamWriter .

¿Hay una solución elegante para este tipo de problema?


Otro enfoque basado en un decorador de tipo XMLStreamWriter que simplemente omitirá el primer carácter de un contenido de texto, sin embargo, no tendrá la capacidad de limitarlo solo a nodos hoja, aplicará la misma lógica a todos los contenidos de texto no solo de nodos de hoja que no serán un problema si su clasificación no genera contenido mixto como en su ejemplo. De hecho, si no tiene contenido mixto (contenido de texto y nodos mezclados), solo los nodos hoja pueden tener contenido de texto.

Su decorador podría ser algo como esto:

public class RemoveFirstCharacter implements XMLStreamWriter { private final XMLStreamWriter delegate; public RemoveFirstCharacter(final XMLStreamWriter delegate) { this.delegate = delegate; } @Override public void writeStartElement(final String localName) throws XMLStreamException { delegate.writeStartElement(localName); } @Override public void writeStartElement(final String namespaceURI, final String localName) throws XMLStreamException { delegate.writeStartElement(namespaceURI, localName); } ... @Override public void writeCharacters(final String text) throws XMLStreamException { // Skip the first character delegate.writeCharacters(text.substring(1)); } @Override public void writeCharacters(final char[] text, final int start, final int len) throws XMLStreamException { if (start == 0) { // Skip the first character delegate.writeCharacters(text, 1, len - 1); } else { delegate.writeCharacters(text, start, len); } } }

Entonces tu código sería:

// Create the marshaller for the class Book JAXBContext jaxbContext = JAXBContext.newInstance(Book.class); Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); // Create the main XMLStreamWriter XMLOutputFactory output = XMLOutputFactory.newInstance(); XMLStreamWriter writer = output.createXMLStreamWriter(System.out); // Apply the custom XMLStreamWriter that will remove the first character // of each text content jaxbMarshaller.marshal(book, new RemoveFirstCharacter(writer));