Last active
November 12, 2021 13:36
-
-
Save ufuk/2872b6b115c281b18a4633b1866f1bc6 to your computer and use it in GitHub Desktop.
Various XML utilities, such as unmarshal and consume XML input stream by target element name (and -optional- target element depth).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import lombok.AccessLevel; | |
import lombok.NoArgsConstructor; | |
import lombok.extern.slf4j.Slf4j; | |
import org.apache.commons.lang3.StringUtils; | |
import javax.xml.bind.JAXBContext; | |
import javax.xml.bind.Unmarshaller; | |
import javax.xml.stream.XMLInputFactory; | |
import javax.xml.stream.XMLStreamReader; | |
import javax.xml.stream.util.StreamReaderDelegate; | |
import javax.xml.transform.Source; | |
import javax.xml.transform.Transformer; | |
import javax.xml.transform.TransformerException; | |
import javax.xml.transform.TransformerFactory; | |
import javax.xml.transform.stream.StreamResult; | |
import java.io.InputStream; | |
import java.io.StringWriter; | |
import java.util.ArrayList; | |
import java.util.List; | |
import java.util.Objects; | |
import java.util.function.Consumer; | |
@Slf4j | |
@NoArgsConstructor(access = AccessLevel.PRIVATE) | |
public final class XmlUtils { | |
public static <T> void unMarshalAndConsume(InputStream inputStream, Class<T> targetClass, String targetElementName, Consumer<T> consumer) throws Exception { | |
unMarshalAndConsume(inputStream, targetClass, targetElementName, null, consumer); | |
} | |
public static <T> void unMarshalAndConsume(InputStream inputStream, Class<T> targetClass, String targetElementName, Integer targetElementDepth, Consumer<T> consumer) throws Exception { | |
XMLStreamReader xmlStreamReader = null; | |
try { | |
final XMLInputFactory xmlInputFactory = XMLInputFactory.newFactory(); | |
xmlStreamReader = xmlInputFactory.createXMLStreamReader(inputStream); | |
final Unmarshaller unmarshaller = JAXBContext.newInstance(targetClass).createUnmarshaller(); | |
int currentDepth = 0; | |
while (xmlStreamReader.hasNext()) { | |
xmlStreamReader.next(); | |
if (xmlStreamReader.isStartElement()) { | |
currentDepth++; | |
if (xmlStreamReader.getLocalName().equals(targetElementName) && (Objects.isNull(targetElementDepth) || targetElementDepth == currentDepth)) { | |
T value = unmarshaller.unmarshal(xmlStreamReader, targetClass).getValue(); | |
consumer.accept(value); | |
} | |
} else if (xmlStreamReader.isEndElement()) { | |
currentDepth--; | |
} | |
} | |
} finally { | |
if (xmlStreamReader != null) { | |
xmlStreamReader.close(); | |
} | |
} | |
} | |
public static <T> List<T> unMarshalAndList(InputStream inputStream, Class<T> targetClass, String targetElementName) throws Exception { | |
return unMarshalAndList(inputStream, targetClass, targetElementName, null); | |
} | |
public static <T> List<T> unMarshalAndList(InputStream inputStream, Class<T> targetClass, String targetElementName, Integer targetElementDepth) throws Exception { | |
final List<T> results = new ArrayList<>(); | |
unMarshalAndConsume(inputStream, targetClass, targetElementName, targetElementDepth, results::add); | |
return results; | |
} | |
public static String toString(Source xmlSource) { | |
try { | |
final StringWriter writer = new StringWriter(); | |
final StreamResult result = new StreamResult(writer); | |
final Transformer transformer = TransformerFactory.newInstance().newTransformer(); | |
transformer.transform(xmlSource, result); | |
return writer.toString(); | |
} catch (TransformerException e) { | |
throw new RuntimeException("XML source couldn't be transformed to String", e); | |
} | |
} | |
public static <T> T unMarshalToTypeByIgnoringNameSpace(Source xmlSource, Class<T> targetClass) throws Exception { | |
final NameSpaceIgnoringXMLStreamReader streamReader = new NameSpaceIgnoringXMLStreamReader(XMLInputFactory.newFactory().createXMLStreamReader(xmlSource)); | |
final Unmarshaller unmarshaller = JAXBContext.newInstance(targetClass).createUnmarshaller(); | |
return unmarshaller.unmarshal(streamReader, targetClass).getValue(); | |
} | |
static class NameSpaceIgnoringXMLStreamReader extends StreamReaderDelegate { | |
public NameSpaceIgnoringXMLStreamReader(XMLStreamReader reader) { | |
super(reader); | |
} | |
@Override | |
public String getAttributeNamespace(int arg0) { | |
return StringUtils.EMPTY; | |
} | |
@Override | |
public String getNamespaceURI() { | |
return StringUtils.EMPTY; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment