PrettyPrinting.Игнорирование пробелов - PullRequest
4 голосов
/ 07 сентября 2010

будь нежным.

Я пытаюсь использовать javax.xml.transform.Transformer для форматирования какой-либо строки xml с отступом / пробелом между тегами. Если между тегами нет пробелов, все работает нормально. Если есть, это действует странно. Я выложу пример. Я пытался развить следующую тему: http://forums.sun.com/thread.jspa?messageID=2054303#2699961. Безуспешно.

Код для следования:

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
   factory.setIgnoringElementContentWhitespace(true);
   DocumentBuilder builder = factory.newDocumentBuilder();
   DOMImplementation domImpl = builder.getDOMImplementation();
   DOMImplementationLS ls = (DOMImplementationLS) domImpl.getFeature("LS", "3.0");
   LSInput in = ls.createLSInput();
   in.setByteStream(new ByteArrayInputStream(input.getBytes()));
   LSParser parser = ls.createLSParser(DOMImplementationLS.MODE_SYNCHRONOUS,
     "http://www.w3.org/2001/XMLSchema");
   Document xmlInput = parser.parse(in);

   StringWriter stringWriter = new StringWriter();
   StreamResult xmlOutput = new StreamResult(stringWriter);
   TransformerFactory f = TransformerFactory.newInstance();
   f.setAttribute("indent-number", 2);

   Transformer transformer = f.newTransformer();
   transformer.setOutputProperty(OutputKeys.INDENT, "yes");
   transformer.setOutputProperty(OutputKeys.METHOD, "xml");
   transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
   transformer.transform(new DOMSource(xmlInput), xmlOutput);

Если между тегами нет прерываний

input : <tag><nested>    hello   </nested></tag>
output : 
<tag>
  <nested>    hello   </nested>
</tag>

Если есть:

input : <tag>  <nested>    hello   </nested></tag>
output : 
<tag>  <nested>    hello   </nested>
</tag>

JVM 1.6.

Что-то здесь не так?

Ответы [ 2 ]

3 голосов
/ 04 марта 2011

Это должно быть проблемой при реализации преобразователя.Я создал небольшой тестовый класс, который читает строку без пробелов и разрывов строк в виде XML и создает преобразователь из таблицы стилей XSLT (также из строки).Таблица стилей указывает, что отступ должен произойти.По сути, это еще один способ достижения того, что вы сделали с transformer.setOutputProperty(OutputKeys.INDENT, "yes");

Вот оно:

package transformation;

import java.io.StringReader;

import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

public class TransformerTest {

    public static void main(String[] args) throws Exception {

        final String xmlSample = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><tag><nested>hello</nested></tag>";
        final String stylesheet = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"><xsl:output method=\"xml\" version=\"1.0\" indent=\"yes\"/><xsl:template match=\"node()|@*\"><xsl:copy><xsl:apply-templates select=\"node()|@*\"/></xsl:copy></xsl:template></xsl:stylesheet>";

        final TransformerFactory factory = TransformerFactory.newInstance();

        final Source xslSource = new StreamSource(new StringReader(stylesheet));
        final Transformer transformer = factory.newTransformer(xslSource);

        final Source source = new StreamSource(new StringReader(xmlSample));
        final Result result = new StreamResult(System.out);

        transformer.transform(source, result);

    }

}

Теперь любопытно, что результаты меняются в зависимости от используемого трансформатора.Если я не размещу реализацию TransformerFactory в пути к классам (используя реализацию по умолчанию в библиотеках JRE), результат будет следующим:

<?xml version="1.0" encoding="UTF-8"?>
<tag>
<nested>hello</nested>
</tag>

Неправильно, поскольку тег не имеет отступ.

Затем, добавив недавнюю реализацию Xalan в classpath (xalan.jar и serializer.jar, все еще используя парсеры JRE по умолчанию / построители DOM), я получаю следующее:

<?xml version="1.0" encoding="UTF-8"?><tag>
<nested>hello</nested>
</tag>

Все еще не правильнопервый тег находится в той же строке, что и объявление XML, и не имеет отступа.

Если честно, это меня шокировало.Я бы понял, если пробел между тегами или вокруг текстовых узлов повлияет на отступ, так как преобразователь может предположить, что некоторые из них не игнорируются.Но видеть простой XML, подобный этому искаженному, довольно странно.Я подумал, что, возможно, использование вывода консоли может иметь какое-то отношение к нему, поэтому я попытался выполнить потоковую передачу в файл.Тот же результат.

Довольно странно, как давно существующие реализации преобразователей все еще имеют такое поведение.Но не так плохо, как когда я заметил, что использование валидатора схемы приводило к удалению атрибутов из «улучшенного» вывода XML.

Так что, похоже, с этим ничего не поделаешь, кроме попытокчтобы найти другие процессоры и посмотреть, есть ли у них такая же проблема.Может быть, Саксон стоит тогоЭтот отчет об ошибке тоже интересен (однако для Java 1.5): http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6296446

0 голосов
/ 06 мая 2015

Похоже, что трансформатору не нравится пустое пространство, поэтому самое простое решение - просто удали это ....

    public String prettyPrintXML(String inXML)  {

       String outXML = inXML;

// The transformer doesn't like white space between tags so remove it.          
           String[] bits = inXML.split(">");      
       inXML="";
       boolean first = true;
       for (int n=0;n<bits.length; n++){
           if (first)
            inXML = inXML + bits[n].trim();
           else
             inXML = inXML + ">"+bits[n].trim();

           first = false;
       }
      inXML = inXML + ">";

Передайте inXML в свой преобразователь и начинайте.

...