Потоковая передача XML посредством преобразования в JAXB Unmarshaller с объявленным типом класса для корневого элемента - PullRequest
4 голосов
/ 17 января 2012

Есть много примеров потоковой передачи XML через XSLT, а затем JAXB в объекты Java.Часто они выглядят так:

Transformer responseTransformer = TransformerFactory.newInstance().newTransformer(new StreamSource(getClass().getResourceAsStream("ResponseTransformation.xsl")));
Unmarshaller jaxbUnmarshaller = JAXBContext.newInstance(ObjectFactory.class.getPackage().getName()).createUnmarshaller();

JAXBResult jaxbResult = new JAXBResult(jaxbUnmarshaller);
responseTransformer.transform(new StreamSource(new StringReader(responseXml)), jaxbResult);
res = jaxbResult.getResult();

Есть также примеры JAXB Unmarshal от объявленного типа , как этот (из Unmarshaller javadoc):

JAXBContext jc = JAXBContext.newInstance( "com.acme.foo" );
Unmarshaller u = jc.createUnmarshaller();

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new File( "nosferatu.xml"));
Element  fooSubtree = ...; // traverse DOM till reach xml element foo, constrained by a 
                           // local element declaration in schema.

// FooType is the JAXB mapping of the type of local element declaration foo.
JAXBElement<FooType> foo = u.unmarshal(fooSubtree, FooType.class);

Обратите внимание, какмы указываем FooType.class для корневого элемента в вызове u.unmarshal(fooSubtree, FooType.class).Хорошо.

Вопрос в следующем: Есть ли способ объединить потоковый способ обработки, как в верхнем примере, со способом указания объявленного типа, как в примере ниже?

Мне нравится способ его достижения, но он требует доступа к классам реализации JAXB.Конечно, это возможно сделать через общедоступный интерфейс JAXB, верно?

Спасибо!

1 Ответ

1 голос
/ 04 декабря 2012

Вы можете получить доступ к методам unmarshaller.unmarshal (source, type), создав XMLFilter. Этот код позволит вам выполнить преобразование и демаршалировать в объект, который не связан с корневым элементом в XSD:

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLFilter;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.util.JAXBResult;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.stream.StreamSource;
import static org.apache.commons.io.IOUtils.closeQuietly;
...
InputStream transformIn = null;
InputStream sourceIn = null;

try {
  // get the transform and source streams.
  transformIn = ...;
  sourceIn = ...;

  // create the filtered source
  SAXTransformerFactory factory = (SAXTransformerFactory)TransformerFactory.newInstance();
  XMLFilter filter = factory.newXMLFilter(new StreamSource(transformIn));
  Source source = new SAXSource(filter, new InputSource(new InputStreamReader(sourceIn, "UTF-8")));

  // unmarshal the object.
  Unmarshaller jaxbUnmarshaller = 
    JAXBContext.newInstance(ObjectFactory.class.getPackage().getName()).createUnmarshaller();
  JAXBElement<FooType> foo = jaxbUnmarshaller.unmarshal(source, FooType.class);
}
finally {
  closeQuietly(transformIn);
  closeQuietly(sourceIn);
}

ПРЕДУПРЕЖДЕНИЕ : То, что вы используете потоковый API, не означает, что реализация является потоковой. Большинство XSLT-процессоров будут создавать представление ввода в стиле DOM перед преобразованием документа. Если вы пытаетесь избежать построения документа перед демаршаллингом, этот код может этого не сделать. См. этот ответ для получения дополнительной информации о процессорах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...