У меня такая проблема:
Теперь я заставил это работать, используя отдельный поток байтов для разбора фрагментов. Я также оборачиваю XMLStream, чтобы избежать открытия / закрытия документа XSLT-преобразователем (Saxon) или закрытия потока.
Однако я считаю, что решение слишком сложное. Должна быть возможность принять контекст JAXB в качестве источника (без промежуточного байтового потока). См. Фрагмент кода:
try {
XMLStreamWriterWrapper writer = getWriter( xmlFile );
for ( Map.Entry<String, String> entry : prefixMapper.getNamespaces().entrySet() ) {
writer.setPrefix( entry.getValue(), entry.getKey() );
}
writer.getWrapperWriter().writeStartDocument();
writer.writeStartElement( GML_URI, "FeatureCollection" );
for ( Map.Entry<String, String> entry : prefixMapper.getNamespaces().entrySet() ) {
writer.getWrapperWriter().writeNamespace( entry.getValue(), entry.getKey() );
}
while ( dtoIterator.hasNext() ) {
writer.writeStartElement( GML_URI, "featureMember" );
D dto = dtoIterator.next();
hideAttributes( dto );
J jaxb = transformToJaxb( dto );
Source untransformed = new JAXBSource( jaxbContext, getRootElement( jaxb ) );
getTransformer().transform( untransformed, new StAXResult( writer) );
writer.writeEndElement();
}
writer.writeEndElement();
writer.getWrapperWriter().writeEndDocument();
writer.getWrapperWriter().flush();
writer.getWrapperWriter().close();
}
catch ( IOException | JAXBException | TransformerException | XMLStreamException e ) {
LOG.error( e );
throw new IllegalArgumentException( e );
}
private XMLStreamWriterWrapper getWriter( File xmlFile ) throws XMLStreamException, FileNotFoundException, IOException {
XMLOutputFactory xof = XMLOutputFactory.newFactory();
xof.setProperty( XMLOutputFactory.IS_REPAIRING_NAMESPACES, Boolean.TRUE );
XMLStreamWriter writer = xof.createXMLStreamWriter( new BufferedOutputStream( new FileOutputStream( xmlFile ) ) );
return new XMLStreamWriterWrapper( writer );
}
Ожидаемый результат (от неоптимизированного решения):
<?xml version = "1.0" ?><gml:FeatureCollection xmlns:gml = "http://www.opengis.net/gml/3.2" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink = "http://www.w3.org/1999/xlink" xmlns:brocom = "http://www.broservices.nl/xsd/brocommon/3.0" xmlns:bro = "http://www.pdok.nl/bro">
<gml:featureMember>
<bro:Characteristics gml:id = "BRO_id_1">
<brocom:broId>id_1</brocom:broId>
</bro:Characteristics>
</gml:featureMember>
<gml:featureMember>
<bro:Characteristics gml:id = "BRO_id_2">
<brocom:broId>id_2</brocom:broId>
</bro:Characteristics>
</gml:featureMember>
Однако результат (из фрагмента кода выше):
<?xml version = "1.0" ?><gml:FeatureCollection xmlns:gml = "http://www.opengis.net/gml/3.2" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink = "http://www.w3.org/1999/xlink" xmlns:brocom = "http://www.broservices.nl/xsd/brocommon/3.0" xmlns:bro = "http://www.pdok.nl/bro">
<gml:featureMember>
<bro:Characteristics gml:id = "BRO_id_1">
<broId xmlns = "http://www.broservices.nl/xsd/brocommon/3.0">id_1</broId>
</bro:Characteristics>
</gml:featureMember>
<gml:featureMember>
<bro:Characteristics gml:id = "BRO_id_2">
<broId xmlns = "http://www.broservices.nl/xsd/brocommon/3.0">id_2</broId>
</bro:Characteristics>
</gml:featureMember>
Вопросов:




Обратите внимание, что вы можете использовать саксонскую реализацию XMLStreamWriter вместо той, которую вы используете (Processor.newSerializer().getXMLStreamWriter()). Возможно, это даст вам больше контроля и, возможно, решит проблемы с пространством имен.
Вместо того, чтобы указывать new StaxResult(writer) в качестве второго аргумента transform(), вы можете попробовать указать new net.sf.saxon.stax.ReceiverToXMLStreamWriter(writer), а затем, возможно, создать подкласс ReceiverToXMLStreamWriter, чтобы вызовы startDocument() и endDocument() ничего не делали.
Что касается обработки пространств имен XMLStreamWriter, я боюсь, что спецификация API очень неясна. Я счел полезным проконсультироваться с http://veithen.github.io/2009/11/01/understanding-stax.html, хотя он не имеет официального статуса. Я не могу дать никаких гарантий, что саксонская интерпретация - это то, что задумали авторы API (нет эталонной реализации или набора тестов).
Использование Processor.newSerializer().getXMLStreamWriter() без конфигурации уже устранило проблему. </br> Ссылка действительно была полезной. Теперь я пишу startDocument, startElement и сразу после инициализирую пространства имен с помощью setPrefix и writeNamespace. Автор, кажется, распознает это и больше не добавляет новые определения пространств имен для вложенных элементов. </br> Спасибо.
@Mickael Kay: Спасибо за ваш ответ. Саксонская реализация XMLStreamWriter выглядит многообещающей. Использование предложенного ReceiverToXMLStreamWriter дает нулевой указатель: в net.sf.saxon.s9api.XsltTransformer.getDestinationReceiver (Xs ltTransformer.java:6 31)