Eu tenho uma String Java que contém XML, sem feeds de linha ou recuos. Gostaria de transformá-lo em uma String com XML bem formatado. Como eu faço isso?
String unformattedXml = "<tag><nested>hello</nested></tag>";
String formattedXml = new [UnknownClass]().format(unformattedXml);
Nota: Minha entrada é uma String . Minha saída é uma String .
Resultado simulado (básico):
<?xml version="1.0" encoding="UTF-8"?>
<root>
<tag>
<nested>hello</nested>
</tag>
</root>
java
xml
pretty-print
Steve McLeod
fonte
fonte
Respostas:
Nota: Os resultados podem variar dependendo da versão do Java. Pesquise soluções alternativas específicas para sua plataforma.
fonte
<?xml version="1.0" encoding="UTF-8"?>
?<?xml ...>
declaração, adicionetransformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes")
doc
definido?Aqui está uma resposta para minha própria pergunta. Combinei as respostas dos vários resultados para escrever uma classe que imprime bastante XML.
Não há garantias de como responde com XML inválido ou documentos grandes.
fonte
writer.getDomConfig().setParameter("format-pretty-print", Boolean.TRUE);
depois daLSSerializer writer = ...
linha.document
foi inicializada, então pensei em adicionar a desaceleração e fazer um rápido exemplo disso. Deixe-me saber se eu deveria mudar alguma coisa, pastebin.com/XL7932aCuma solução mais simples com base nesta resposta :
caso de teste:
retorna:
fonte
factory.setAttribute("indent-number", 4);
e agora funciona.<?xml version="1.0" encoding="UTF-8"?>
?transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
<?xml version="1.0" encoding="UTF-8"?><root>
é tudo em uma linha. Alguma idéia do porquê?transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, "yes");
funcionou para mim.Agora é 2012 e o Java pode fazer mais do que costumava fazer com XML, gostaria de adicionar uma alternativa à minha resposta aceita. Isso não tem dependências fora do Java 6.
fonte
Apenas observe que a resposta mais bem avaliada requer o uso de xerces.
Se você não deseja adicionar essa dependência externa, pode simplesmente usar as bibliotecas jdk padrão (que na verdade são criadas usando xerces internamente).
NB: Houve um erro na versão 1.5 do jdk, consulte http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6296446, mas está resolvido agora.,
(Observe que, se ocorrer um erro, isso retornará o texto original)
fonte
Imprimi no passado usando o método org.dom4j.io.OutputFormat.createPrettyPrint ()
fonte
prettyPrintedString.replaceAll("\\s+\n", "\n")
Aqui está uma maneira de fazê-lo usando dom4j :
Importações:
Código:
fonte
<?xml version...
em uma linha e tudo mais em outra linha.Desde que você está começando com a
String
, é necessário ocultar umDOM
objeto (por exemploNode
) antes de poder usar oTransformer
. No entanto, se você souber que sua string XML é válida e não desejar incorrer na sobrecarga de memória ao analisar uma string em um DOM, execute uma transformação no DOM para recuperar uma string - você pode fazer algo antiquado caractere por análise de caractere. Insira uma nova linha e espaços após todos os</...>
caracteres, mantenha e recue o contador (para determinar o número de espaços) que você incrementa para todos<...>
e diminui para todos os</...>
que vê.Isenção de responsabilidade - fiz uma edição de recortar / colar / texto das funções abaixo, para que elas não sejam compiladas como estão.
fonte
Se o uso de uma biblioteca XML de terceiros estiver correto, você poderá obter algo significativamente mais simples do que o sugerido pelas respostas mais votadas no momento .
Foi declarado que entrada e saída devem ser Strings, então aqui está um método utilitário que faz exatamente isso, implementado com a biblioteca XOM :
Eu testei que funciona, e os resultados não dependem da sua versão do JRE ou de algo parecido. Para ver como personalizar o formato de saída ao seu gosto, dê uma olhada na
Serializer
API.Na verdade, isso saiu por mais tempo do que eu pensava - algumas linhas extras eram necessárias porque
Serializer
quer umaOutputStream
escrita. Mas observe que há muito pouco código para o XML real girando aqui.(Esta resposta faz parte da minha avaliação do XOM, que foi sugerida como uma opção na minha pergunta sobre a melhor biblioteca Java XML para substituir o dom4j. Para o registro, com o dom4j, você pode conseguir isso com uma facilidade semelhante usando
XMLWriter
eOutputFormat
. Edit : .. . como demonstrado na resposta do mlo55 .)fonte
Kevin Hakanson disse: "No entanto, se você sabe que sua string XML é válida e não deseja incorrer na sobrecarga de memória de analisar uma string em um DOM, execute uma transformação no DOM para recuperar uma string - você pode basta fazer algum caractere antiquado pela análise de caracteres. Insira uma nova linha e espaços após todos os caracteres, mantenha e recue o contador (para determinar o número de espaços) que você incrementa a cada <...> e decrementa a cada exibição. "
Acordado. Essa abordagem é muito mais rápida e possui muito menos dependências.
Solução de exemplo:
fonte
Hmmm ... enfrentou algo assim e é um bug conhecido ... basta adicionar este OutputProperty ..
Espero que isto ajude ...
fonte
Sobre o comentário de que "você deve primeiro construir uma árvore DOM": Não, você não precisa e não deve fazer isso.
Em vez disso, crie um StreamSource (novo StreamSource (novo StringReader (str)) e alimente isso ao transformador de identidade mencionado. Isso usará o analisador SAX e o resultado será muito mais rápido. Construir uma árvore intermediária é uma sobrecarga pura para este caso. Caso contrário, a resposta mais bem classificada é boa.
fonte
Usando scala:
Você também pode fazer isso em Java, se depender do scala-library.jar. Se parece com isso:
O
PrettyPrinter
objeto é construído com duas entradas, sendo a primeira a extensão máxima da linha e a segunda a etapa de indentação.fonte
versão ligeiramente melhorada de milosmns ...
fonte
} else if (row.startsWith("</")) {
parte a esta:else if (row.startsWith("</")) { String indent = repeatIdent(--stack); if (pretty.charAt(pretty.length() - 1) == '\n') { pretty.append(indent + row + "\n"); } else { pretty.append(row + "\n"); } }
Apenas para referência futura, aqui está uma solução que funcionou para mim (graças a um comentário que @George Hawkins postou em uma das respostas):
fonte
Se você tem certeza de que possui um XML válido, este é simples e evita árvores XML DOM. Talvez tenha alguns bugs, comente se vir alguma coisa
fonte
Todas as soluções acima não funcionaram para mim, então eu achei isso http://myshittycode.com/2014/02/10/java-properly-indenting-xml-string/
A dica é remover espaços em branco com o XPath
fonte
Este código abaixo funcionando perfeitamente
fonte
Eu misturo todos eles e escrevo um pequeno programa. Ele está lendo o arquivo xml e imprimindo. Apenas em vez de xzy, forneça o caminho do arquivo.
fonte
Apenas mais uma solução que funciona para nós
fonte
Usando jdom2: http://www.jdom.org/
fonte
Como alternativa às respostas de max , codeskraps , David Easley e milosmns , veja minha biblioteca leve e de alto desempenho de impressoras bonitas: xml-formatter
Às vezes, como ao executar serviços SOAP simulados diretamente do arquivo, é bom ter uma impressora bonita que também lide com XML já impresso:
Como alguns comentaram, a impressão bonita é apenas uma maneira de apresentar XML de uma forma mais legível por humanos - o espaço em branco não pertence estritamente aos seus dados XML.
A biblioteca é destinada à impressão bonita para fins de registro e também inclui funções para filtragem (remoção / anonimização de subárvore) e impressão bonita de XML nos nós CDATA e Texto.
fonte
Eu tive o mesmo problema e estou tendo grande sucesso com o JTidy ( http://jtidy.sourceforge.net/index.html )
Exemplo:
fonte
Sublinhado-java tem método estático
U.formatXml(string)
. Eu sou o mantenedor do projeto. Exemplo ao vivoResultado:
fonte
existe um utilitário xml de linha de comando muito bom chamado xmlstarlet ( http://xmlstar.sourceforge.net/ ) que pode fazer muitas coisas que muitas pessoas usam.
Você pode executar esse programa programaticamente usando Runtime.exec e, em seguida, ler o arquivo de saída formatado. Possui mais opções e melhores relatórios de erros do que algumas linhas de código Java podem fornecer.
faça o download do xmlstarlet: http://sourceforge.net/project/showfiles.php?group_id=66612&package_id=64589
fonte
Eu descobri que no Java 1.6.0_32 o método normal para imprimir bastante uma string XML (usando um Transformer com um xslt nulo ou de identidade) não se comporta como eu gostaria se as tags fossem apenas separadas por espaços em branco, em vez de não serem separadas. texto. Eu tentei usar
<xsl:strip-space elements="*"/>
no meu modelo sem sucesso. A solução mais simples que encontrei foi reduzir o espaço da maneira que eu queria usando um filtro SAXSource e XML. Como minha solução foi para registro, eu também estendi isso para trabalhar com fragmentos XML incompletos. Observe que o método normal parece funcionar bem se você usar um DOMSource, mas eu não queria usá-lo devido à incompletude e sobrecarga de memória.fonte
As soluções que encontrei aqui para Java 1.6+ não reformatam o código se ele já estiver formatado. O que funcionou para mim (e re-formatou o código já formatado) foi o seguinte.
É uma boa ferramenta para usar em seus testes de unidade para comparar xml de cadeia completa.
fonte
Para quem procura uma solução rápida e suja - que não precisa que o XML seja 100% válido. por exemplo, no caso de registro REST / SOAP (você nunca sabe o que os outros enviam ;-))
Encontrei e avancei um código snippet que encontrei on-line, que acho que ainda falta aqui como uma abordagem possível válida:
aqui está a saída:
fonte
eu vi uma resposta usando
Scala
, então aqui está outraGroovy
, caso alguém ache interessante. O recuo padrão é 2 etapas, oXmlNodePrinter
construtor também pode receber outro valor.Uso do Java se o jar groovy estiver no caminho de classe
fonte
Caso você não precise de indentação tanto, mas algumas quebras de linha, isso pode ser suficiente para simplesmente regexar ...
O código é bom, não o resultado devido à falta de recuo.
(Para soluções com recuo, consulte outras respostas.)
fonte