Mam ciąg Java, który zawiera XML, bez żadnych linii i wcięć. Chciałbym przekształcić go w String z ładnie sformatowanym XML. Jak mam to zrobic?
String unformattedXml = "<tag><nested>hello</nested></tag>";
String formattedXml = new [UnknownClass]().format(unformattedXml);
Uwaga: Moje dane wejściowe są ciągiem . Mój wynik to ciąg .
(Podstawowy) wynik próbny:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<tag>
<nested>hello</nested>
</tag>
</root>
java
xml
pretty-print
Steve McLeod
źródło
źródło
Odpowiedzi:
Uwaga: wyniki mogą się różnić w zależności od wersji Java. Wyszukaj obejścia specyficzne dla Twojej platformy.
źródło
<?xml version="1.0" encoding="UTF-8"?>
?<?xml ...>
deklarację, dodajtransformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes")
doc
zdefiniowane?Oto odpowiedź na moje własne pytanie. Połączyłem odpowiedzi z różnych wyników, aby napisać klasę, która ładnie drukuje XML.
Brak gwarancji na to, jak zareaguje przy użyciu nieprawidłowego XML lub dużych dokumentów.
źródło
writer.getDomConfig().setParameter("format-pretty-print", Boolean.TRUE);
poLSSerializer writer = ...
wierszu.document
inicjowania zmiennej , więc pomyślałem, że mogę dodać opóźnienie i zrobić z niego szybki przykład. Daj mi znać, jeśli powinienem coś zmienić, pastebin.com/XL7932aCprostsze rozwiązanie oparte na tej odpowiedzi :
walizka testowa:
zwroty:
źródło
factory.setAttribute("indent-number", 4);
i teraz działa.<?xml version="1.0" encoding="UTF-8"?>
?transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
<?xml version="1.0" encoding="UTF-8"?><root>
wszystko jest w jednej linii. Jakieś pomysły dlaczego?transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, "yes");
działało dla mnie.Teraz jest 2012, a Java może zrobić więcej niż kiedyś z XML, chciałbym dodać alternatywę do mojej zaakceptowanej odpowiedzi. Nie ma żadnych zależności poza Javą 6.
źródło
Wystarczy zauważyć, że najwyżej oceniana odpowiedź wymaga użycia kserografów.
Jeśli nie chcesz dodawać tej zewnętrznej zależności, możesz po prostu użyć standardowych bibliotek jdk (które są budowane wewnętrznie przy użyciu xerces).
Uwaga: Wystąpił błąd w wersji 1.5 jdk, patrz http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6296446 ale problem został już rozwiązany.,
(Uwaga: jeśli wystąpi błąd, spowoduje to zwrócenie oryginalnego tekstu)
źródło
Mam dość drukowane w przeszłości za pomocą org.dom4j.io.OutputFormat.createPrettyPrint () metoda
źródło
prettyPrintedString.replaceAll("\\s+\n", "\n")
Oto sposób na zrobienie tego przy użyciu dom4j :
Import:
Kod:
źródło
<?xml version...
w jednej linii i wszystko inne w innej linii.Ponieważ zaczynasz od a
String
, musisz ukryć się przedDOM
obiektem (np.Node
) Przed użyciemTransformer
. Jeśli jednak wiesz, że łańcuch XML jest prawidłowy i nie chcesz ponosić narzutu pamięci podczas analizowania łańcucha w DOM, a następnie uruchom transformację w DOM, aby odzyskać łańcuch - możesz po prostu zrobić trochę staromodny parsowanie znak po znaku. Wstaw nowy wiersz i spacje po każdym</...>
znaku, zachowaj i wcięcie licznika (aby określić liczbę spacji), które zwiększasz dla każdego<...>
i zmniejszaj dla każdego</...>
, widzisz.Oświadczenie - Zrobiłem edycję wycinania / wklejania / tekstu dla poniższych funkcji, więc mogą się nie kompilować w obecnej postaci.
źródło
Jeśli korzystanie z biblioteki XML innej firmy jest w porządku, możesz uciec od czegoś znacznie prostszego niż to, co obecnie najlepiej głosuje odpowiedzi sugerują .
Stwierdzono, że zarówno dane wejściowe, jak i wyjściowe powinny być ciągami, więc oto metoda narzędziowa, która właśnie to robi, zaimplementowana w bibliotece XOM :
Testowałem, że to działa, a wyniki nie zależą od twojej wersji JRE ani niczego podobnego. Aby zobaczyć, jak dostosować format wyjściowy do swoich potrzeb, spójrz na
Serializer
API.To faktycznie wyszło dłużej, niż myślałem - potrzebne były dodatkowe wiersze, ponieważ
Serializer
chciałbymOutputStream
napisać do. Zauważ jednak, że jest tu bardzo mało kodu do faktycznego kręcenia XML.(Ta odpowiedź jest częścią mojej oceny XOM, która została zasugerowana jako jedna z opcji mojego pytania o najlepszą bibliotekę Java XML, która zastąpiłaby dom4j. Dla przypomnienia, z dom4j można to osiągnąć z podobną łatwością przy użyciu
XMLWriter
iOutputFormat
. Edytuj : .. . wykazano w odpowiedzi mlo55 ).źródło
Kevin Hakanson powiedział: „Jeśli jednak wiesz, że łańcuch XML jest prawidłowy i nie chcesz ponosić dodatkowej pamięci związanej z analizowaniem łańcucha w DOM, a następnie uruchamianiem transformacji w DOM, aby odzyskać łańcuch - możesz po prostu parsuj staroświecką postać po analizie znaków. Wstawianie nowego wiersza i spacji po każdym znaku, zachowaj i wcięcie licznika (aby określić liczbę spacji), które zwiększasz dla każdego <...> i zmniejszaj dla każdego, co widzisz. "
Zgoda. Takie podejście jest znacznie szybsze i ma znacznie mniej zależności.
Przykładowe rozwiązanie:
źródło
Hmmm ... napotkałem coś takiego i jest to znany błąd ... po prostu dodaj ten OutputProperty ..
Mam nadzieję że to pomoże ...
źródło
W odniesieniu do komentarza, że „musisz najpierw zbudować drzewo DOM”: Nie, nie musisz i nie powinieneś tego robić.
Zamiast tego utwórz StreamSource (nowy StreamSource (nowy StringReader (str)) i podaj go do wspomnianego transformatora tożsamości. Użyje on analizatora składni SAX, a wynik będzie znacznie szybszy. Budowanie drzewa pośredniego jest w tym przypadku czystym kosztem. W przeciwnym razie odpowiedź na najwyższym miejscu jest dobra.
źródło
Za pomocą scala:
Możesz to zrobić również w Javie, jeśli zależy Ci na scala-library.jar. To wygląda tak:
PrettyPrinter
Przedmiot zbudowany jest z dwóch wskazówki, z których pierwszy jest maksymalna długość wiersza a druga jest etap wgłębieniem.źródło
nieco ulepszona wersja z milosmns ...
źródło
} else if (row.startsWith("</")) {
część na to: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"); } }
Dla odniesienia w przyszłości, oto rozwiązanie, które zadziałało dla mnie (dzięki komentarzowi, który @George Hawkins opublikował w jednej z odpowiedzi):
źródło
Jeśli masz pewność, że masz prawidłowy kod XML, ten jest prosty i pozwala uniknąć drzew DOM XML. Może ma jakieś błędy, skomentuj, jeśli coś zobaczysz
źródło
Wszystkie powyższe rozwiązania nie działały dla mnie, a potem to znalazłem http://myshittycode.com/2014/02/10/java-properly-indenting-xml-string/
Wskazówką jest usunięcie białych znaków za pomocą XPath
źródło
Poniższy kod działa idealnie
źródło
Łączę je wszystkie i piszę jeden mały program. Odczytuje z pliku xml i drukuje. Po prostu Zamiast xzy podaj ścieżkę do pliku.
źródło
Kolejne rozwiązanie, które działa dla nas
źródło
Korzystanie z jdom2: http://www.jdom.org/
źródło
Jako alternatywę dla odpowiedzi od max , codekraps , David Easley i milosmns , spójrz na moją lekką, wydajną bibliotekę ładnych drukarek: xml-formatter
Czasami, na przykład podczas uruchamiania fałszywych usług SOAP bezpośrednio z pliku, dobrze jest mieć ładną drukarkę, która obsługuje również już ładnie wydrukowane XML:
Jak niektórzy komentowali, ładne drukowanie to tylko sposób prezentacji XML w bardziej czytelnej dla człowieka formie - białe znaki ściśle nie należą do twoich danych XML.
Biblioteka jest przeznaczona do ładnego drukowania do celów logowania, a także zawiera funkcje do filtrowania (usuwanie / anonimizacja poddrzewa) i ładnego drukowania XML w węzłach CDATA i Text.
źródło
Miałem ten sam problem i odnoszę wielki sukces z JTidy ( http://jtidy.sourceforge.net/index.html )
Przykład:
źródło
Underscore-java ma metodę statyczną
U.formatXml(string)
. Jestem opiekunem projektu. Przykład na żywoWynik:
źródło
istnieje bardzo ładne narzędzie xml z linii poleceń o nazwie xmlstarlet ( http://xmlstar.sourceforge.net/ ), które może robić wiele rzeczy, z których korzysta wiele osób.
Możesz uruchomić ten program programowo za pomocą Runtime.exec, a następnie odczytać sformatowany plik wyjściowy. Ma więcej opcji i lepsze raportowanie błędów niż kilka wierszy kodu Java.
pobierz xmlstarlet: http://sourceforge.net/project/showfiles.php?group_id=66612&package_id=64589
źródło
Odkryłem, że w Javie 1.6.0_32 normalna metoda ładnego drukowania łańcucha XML (przy użyciu transformatora z zerowym lub identyfikatorem xslt) nie zachowuje się tak, jak chciałbym, jeśli znaczniki są tylko oddzielone białymi spacjami, w przeciwieństwie do braku oddzielania tekst. Próbowałem użyć
<xsl:strip-space elements="*"/>
w swoim szablonie bezskutecznie. Najprostszym rozwiązaniem, jakie znalazłem, było usunięcie przestrzeni tak, jak chciałem, za pomocą filtru SAXSource i XML. Ponieważ moim rozwiązaniem było logowanie, rozszerzyłem to również na niekompletne fragmenty XML. Zauważ, że normalna metoda wydaje się działać dobrze, jeśli używasz DOMSource, ale nie chciałem jej używać z powodu niekompletności i obciążenia pamięci.źródło
Rozwiązania, które znalazłem tutaj dla Java 1.6+, nie formatują kodu, jeśli jest już sformatowany. Ten, który zadziałał dla mnie (i ponownie sformatował już sformatowany kod), był następujący.
Jest to dobre narzędzie do użycia w testach jednostkowych do pełnego porównania xml.
źródło
Dla tych, którzy szukają szybkiego i brudnego rozwiązania - które nie musi być w 100% poprawne. np. w przypadku rejestrowania REST / SOAP (nigdy nie wiadomo, co wysyłają inni ;-))
Znalazłem i ulepszyłem wycięty kod, który znalazłem w sieci, ale myślę, że wciąż tutaj go brakuje, ponieważ jest to poprawne możliwe podejście:
oto wynik:
źródło
Widziałem jedną odpowiedź użyciu
Scala
, więc tutaj jest jeszcze jeden wGroovy
, na wypadek gdyby ktoś znajdzie to ciekawe. Domyślne wcięcie to 2 kroki,XmlNodePrinter
konstruktorowi można również przekazać inną wartość.Użycie z Javy, jeśli groovy jar znajduje się w ścieżce klas
źródło
Jeśli nie potrzebujesz tyle wcięć, ale kilku podziałów linii, wystarczy po prostu regexować ...
Kod jest fajny, a nie wynik z powodu braku wcięcia.
(W przypadku rozwiązań z wcięciem zobacz inne odpowiedzi.)
źródło