Добавить комментарии XML в файл с маршалированием

Я собираю объекты в XML файл. Как добавить комментарии в этот XML файл?

Ответы

Ответ 1

Я не вижу способа сделать это только с JAXB. Однако, я думаю, вы можете использовать DOM для получения желаемого эффекта:

final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
final DocumentBuilder builder = factory.newDocumentBuilder();
final Document doc = builder.getDOMImplementation().createDocument(null, null, null);

final Binder<Node> binder = jaxbContext.createBinder();
binder.marshal(jaxbObject, doc);
final Comment comment = doc.createComment("This is a comment");
doc.appendChild(comment);

final DOMSource domSource = new DOMSource(doc);
// use System.out for testing
final StreamResult streamResult = new StreamResult(System.out);
final TransformerFactory tf = TransformerFactory.newInstance();
final Transformer serializer = tf.newTransformer();
serializer.transform(domSource, streamResult);

Где jaxbContext - это объект JAXBContext, с которым вы работаете, и jaxbObject - объект, который должен быть настроен. Этот пример просто добавляет комментарий в конец документа. Для другого местоположения вам нужно будет пересечь DOM через объект doc или использовать XPath, чтобы найти точный элемент, который вы хотите добавить комментарий, и использовать appendChild на нем.

Ответ 2

Вы можете добавлять комментарии сразу после преамбулы с фирменным свойством Marshaller com.sun.xml.bind.xmlHeaders(см. XML Preamble Control)

В включенной JAXB-реализации jdk1.6.0_29 свойство называется "com.sun.xml.internal.bind.xmlHeaders"

См. также вопрос: Как добавить инструкции обработки DOCTYPE и xml при сортировке с помощью JAXB?

Итак, чтобы получить этот XML с комментарием test после преамбулы:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- Test Comment -->
<player>
    <name>Daniel</name>
    <birthday>1982-06-09T00:00:00+02:00</birthday>
</player>

Вы можете использовать этот Java-код:

JAXBContext context = JAXBContext.newInstance(Player.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
m.setProperty("com.sun.xml.internal.bind.xmlHeaders", "\n<!-- Test Comment -->");
m.marshal(player, System.out);

Ответ 3

Если кто-то приходит к этому сейчас, как я это делал, стоит указать, что свойство сделать это теперь com.sun.xml.bind.xmlHeaders (больше не кажется внутренним), так что вы можете решить проблему вроде этого (у меня есть только попробовал это с EclipseLink MOXY):

JAXBContext context = JAXBContext.newInstance(Player.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
m.setProperty("com.sun.xml.bind.xmlHeaders", "\n<!-- Test Comment -->");
m.marshal(player, System.out);

Следующая информация первоначально получена из Свойства Маршалла в Расширения JAXB RI на jaxb.java.net:

Управление преамбулой XML

Это свойство позволяет указать преамбулу XML ( декларация) и любые дополнительные PI, комментарии, декларация DOCTYPE который следует за ним. Это свойство вступает в силу только тогда, когда вы marshalling для OutputStream, Writer или StreamResult. Обратите внимание, что это свойство взаимодействует с свойством Marshaller.JAXB_FRAGMENT. Если это свойство нетронутым или установлено в false, тогда JAXB всегда будет писать его преамбулу XML, поэтому это свойство можно использовать только для написания PI, комментарии, DOCTYPE и т.д. С другой стороны, если для него установлено значение true, то JAXB не будет писать собственную преамбулу XML, поэтому это свойство может содержать пользовательский XML-преамбула.