Поскольку перемещение в java 1.7 Xml Document Element не является отступом

Я пытаюсь сделать отступ XML, созданный Transformer. Все DOM Node являются отступом, как ожидалось, за исключением первого Node - элемента документа. элемент документа не запускается в новой строке, а просто согласуется сразу после объявления XML.

Эта ошибка возникает, когда я перешел на java 1.7, при использовании java 1.6 или 1.5 этого не происходит.

Мой код:

ByteArrayOutputStream s = new OutputStreamWriter(out, "utf-8");

TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount","4");

transformer.transform(new DOMSource(doc), new StreamResult(s));

Выход:

<?xml version="1.0" encoding="UTF-8"?><a>
       <b>bbbbb</b>
 </a>

Кто-нибудь знает, почему?

Кстати, когда я добавляю свойство

transformer.setOutputProperty(OutputKeys.STANDALONE, "yes");

Работает так, как ожидалось, но объявление xml изменяется, теперь у него есть автономное свойство, и я не хочу изменять объявление xml.

Ответ 1

Хорошо,

Я нашел в Java API следующее:

Если указано свойство doctype-system, метод вывода xml должен вывести объявление типа документа непосредственно перед первым элементом.

SO Я использовал это свойство

 transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, "yes");

и он решает мою проблему без изменения моего объявления xml.

Спасибо.

Ответ 2

Для меня написать декларацию XML в Writer или OutputStream перед тем, как писать XML и сказать, что трансформатор пропустить объявление, это единственное, что сработало. Единственное другое решение для сохранения интервала - это библиотека VTD-XML.

    StringBuilder sb = new StringBuilder();
    sb.append("<?xml version=\"").append(doc.getXmlVersion()).append("\"");
    sb.append(" encoding=\"").append(doc.getXmlEncoding()).append("\"");
    if (doc.getXmlStandalone()) {
        sb.append(" standalone=\"").append("" + doc.getXmlStandalone()).append("\"");
    }
    sb.append("?>").append("\n");

    writer.write(sb.toString());
            TransformerFactory tf = TransformerFactory.newInstance();
    try {
        Transformer transformer = tf.newTransformer();
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
    }
    catch (Exception e)  {
    //snipped out for brevity
    }

Ответ 3

Это, кажется, проблема (ошибка) реализации XML в Java. Единственный способ получить строку после объявления XML - явно указать атрибут standalone. Вы можете установить его на no, что является неявным значением по умолчанию, даже если оно совершенно не имеет значения, если не используется DTD.

Ответ 4

Xalan в какой-то момент изменил поведение символа новой строки после объявления XML.

OpenJDK (и, следовательно, Oracle JDK тоже) внедрил обходной путь для этой проблемы. Это обходное решение можно включить, установив специальное свойство в объект Transformer:

try {
    transformer.setOutputProperty("http://www.oracle.com/xml/is-standalone", "yes");
} catch (IllegalArgumentException e) {
    // Might be thrown by JDK versions not implementing the workaround.
} 

Таким образом, старое поведение (печать символа новой строки после объявления XML) восстанавливается без добавления автономного атрибута в декларацию XML.