2014-11-17 2 views
0

В этой теме есть дюжина потоков, но все они содержат ответы, которые не работают для меня удовлетворительным образом. Кажется, нужно использовать конкретную реализацию DOM. Тем не менее, я не могу заставить его читать входные данные XML:Довольно печатать XML с использованием Java

@Test 
public void testPrettyPrintConvertDomLevel3() throws UnsupportedEncodingException { 
    String unformattedXml 
      = "<?xml version=\"1.0\" encoding=\"UTF-16\"?><QueryMessage\n" 
      + "  xmlns=\"http://www.SDMX.org/resources/SDMXML/schemas/v2_0/message\"\n" 
      + "  xmlns:query=\"http://www.SDMX.org/resources/SDMXML/schemas/v2_0/query\">\n" 
      + " <Query>\n" 
      + "  <query:CategorySchemeWhere>\n" 
      + " \t\t\t\t\t   <query:AgencyID>ECB\n\n\n\n</query:AgencyID>\n" 
      + "  </query:CategorySchemeWhere>\n" 
      + " </Query>\n\n\n\n\n" 
      + "</QueryMessage>"; 

    System.out.println(prettyPrintWithXercesDomLevel3(unformattedXml.getBytes("UTF-16"))); 
} 

Вот метод:

public static String prettyPrintWithXercesDomLevel3(byte[] input) { 
    try { 
//System.setProperty(DOMImplementationRegistry.PROPERTY,"org.apache.xerces.dom.DOMImplementationSourceImpl"); 
     DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance(); 
     DOMImplementationLS impl = (DOMImplementationLS) registry.getDOMImplementation("XML 3.0 LS 3.0"); 
     if (impl == null) { 
      throw new RuntimeException("No DOMImplementation found !"); 
     } 

     log.info(String.format("DOMImplementationLS: %s", impl.getClass().getName())); 

     LSParser parser = impl.createLSParser(
       DOMImplementationLS.MODE_SYNCHRONOUS, 
       //"http://www.w3.org/2001/XMLSchema"); 
       "http://www.w3.org/TR/REC-xml"); 
     log.info(String.format("LSParser: %s", parser.getClass().getName())); 
     LSInput lsi = impl.createLSInput(); 
     lsi.setByteStream(new ByteArrayInputStream(input)); 
     Document doc = parser.parse(lsi); 

     LSSerializer serializer = impl.createLSSerializer(); 
     serializer.getDomConfig().setParameter("format-pretty-print",Boolean.TRUE); 
     LSOutput output = impl.createLSOutput(); 
     output.setEncoding("UTF-8"); 
     ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
     output.setByteStream(baos); 
     serializer.write(doc, output); 
     return baos.toString(); 
//   return serializer.writeToString(doc); 
    } catch (Exception e) { 
     throw new RuntimeException(e); 
    } 
} 

Однако довольно-печать не работает. Есть идеи?

+0

попробуйте изменить 'xml.getBytes()' в 'xml.getBytes ("UTF-8")' –

+0

Как примечание стороны, я бы рассмотреть возможность использования [StringBuilder] (https://docs.oracle.com/javase/7/docs/api/java/lang/StringBuilder.html) – victorantunes

+0

в качестве примечания, это только пример. и строка находится в ASCII. Если вы не знаете о внутренности XML Java, пропустите эту тему. – user1050755

ответ

0

import java.io.StringReader; 
 
import javax.xml.parsers.DocumentBuilderFactory; 
 
import org.w3c.dom.Node; 
 
import org.w3c.dom.bootstrap.DOMImplementationRegistry; 
 
import org.w3c.dom.ls.DOMImplementationLS; 
 
import org.w3c.dom.ls.LSSerializer; 
 
import org.xml.sax.InputSource; 
 

 
/** 
 
* 
 
* @author lananda 
 
*/ 
 
public class PrettyXmlWriter { 
 
    
 
    public static void main(String... args){ 
 
     String unformattedXml 
 
       = "<?xml version=\"1.0\" encoding=\"UTF-16\"?>" 
 
       + "<QueryMessage\n" 
 
       + "  xmlns=\"http://www.SDMX.org/resources/SDMXML/schemas/v2_0/message\"\n" 
 
       + "  xmlns:query=\"http://www.SDMX.org/resources/SDMXML/schemas/v2_0/query\">\n" 
 
       + " <Query>\n" 
 
       + "  <query:CategorySchemeWhere>\n" 
 
       + " \t\t\t\t\t   <query:AgencyID>ECB\n\n\n\n</query:AgencyID>\n" 
 
       + "  </query:CategorySchemeWhere>\n" 
 
       + " </Query>\n\n\n\n\n" 
 
       + "</QueryMessage>"; 
 
     unformattedXml = unformattedXml.replaceAll("\\s+", " "); 
 
     String format = format(unformattedXml); 
 
     System.out.println(format); 
 
    } 
 

 
     public static String format(String xml) { 
 
     try { 
 
      final InputSource src = new InputSource(new StringReader(xml)); 
 
      final Node document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(src).getDocumentElement(); 
 
      final Boolean keepDeclaration = Boolean.valueOf(xml.startsWith("<?xml")); 
 

 
     //May need this: System.setProperty(DOMImplementationRegistry.PROPERTY,"com.sun.org.apache.xerces.internal.dom.DOMImplementationSourceImpl"); 
 
      final DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance(); 
 
      final DOMImplementationLS impl = (DOMImplementationLS) registry.getDOMImplementation("LS"); 
 
      final LSSerializer writer = impl.createLSSerializer(); 
 
      writer.getDomConfig().setParameter("format-pretty-print", Boolean.TRUE); // Set this to true if the output needs to be beautified. 
 
      writer.getDomConfig().setParameter("xml-declaration", keepDeclaration); // Set this to true if the declaration is needed to be outputted. 
 
      return writer.writeToString(document); 
 
     } catch (Exception e) { 
 
      throw new RuntimeException(e); 
 
     } 
 
    } 
 
}

+0

вы были наполовину правы: с использованием getBytes() предполагается UTF-8/ASCII, поэтому я использовал getBytes («UTF-16»), и теперь все в порядке. Исходная кодировка - UTF-8. – user1050755

0

Кодировка исходного файла Java также должны соответствовать тому, что вы пытаетесь запустить с. Если вы используете Eclipse, по умолчанию по умолчанию используется CP-1252. Первое, что я делаю, когда добавляю новую версию Eclipse, - это изменение кодировки файла в UTF-8.

Я использовал ваш код, и он работал отлично, так как кодировка исходного кода была UTF-8.

+0

полностью правильно. Тем не менее, довольно-печатная версия не работает для меня. – user1050755

0

Обновление: кажется, что all whitespace is significant in XML: «Основываясь на спецификации W3C XML, XML-парсеры Oracle XML Developer Kit (XDK) по умолчанию сохраняют все пробелы». Поэтому вполне разумно NOT сделать эту функциональную часть публичного API. org.jdom2 обеспечивает разумную реализацию:

@Test 
public void testPrettyPrintConvertDomLevel3() throws UnsupportedEncodingException, JDOMException, IOException { 
    String unformattedXml 
      = "<?xml version=\"1.0\" encoding=\"UTF-16\"?><QueryMessage\n" 
      + "  xmlns=\"http://www.SDMX.org/resources/SDMXML/schemas/v2_0/message\"\n" 
      + "  xmlns:query=\"http://www.SDMX.org/resources/SDMXML/schemas/v2_0/query\">\n" 
      + " <Query>\n" 
      + "  <query:CategorySchemeWhere>\n" 
      + " \t\t\t\t\t   <query:AgencyID>ECB \n </query:AgencyID>\n" 
      + "  </query:CategorySchemeWhere>\n" 
      + " </Query>\n\n\n\n\n" 
      + "</QueryMessage>"; 
    SAXBuilder builder = new SAXBuilder(); 
    Document doc = builder.build(new ByteArrayInputStream(unformattedXml.getBytes("UTF-16"))); 
    Format f = Format.getPrettyFormat(); 
    f.setLineSeparator(LineSeparator.NL); 
    f.setTextMode(Format.TextMode.TRIM_FULL_WHITE); 
    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    new XMLOutputter(f).output(doc, baos); 
    assertEquals("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" 
      + "<QueryMessage xmlns=\"http://www.SDMX.org/resources/SDMXML/schemas/v2_0/message\" xmlns:query=\"http://www.SDMX.org/resources/SDMXML/schemas/v2_0/query\">\n" 
      + " <Query>\n" 
      + " <query:CategorySchemeWhere>\n" 
      + "  <query:AgencyID>ECB \n" 
      + " </query:AgencyID>\n" 
      + " </query:CategorySchemeWhere>\n" 
      + " </Query>\n" 
      + "</QueryMessage>\n", baos.toString()); 
} 
Смежные вопросы