2012-03-14 9 views
17

Używam Spring, CXF i Hibernate do budowy usługi WebService, która wykonuje kwerendy wyszukiwania w zagranicznej bazie danych, że mam dostęp tylko do odczytu.Jak radzić sobie z nieprawidłowymi znakami na wyjściu WS podczas używania CXF?

Problem polega na tym, że niektóre wpisy w bazie danych mają dziwne znaki (0x2) w polach tekstowych i wydaje się, że CXF lub biblioteka (Aegis?), Której używa do przetwarzania/serializacji obiektów zwróconych z sesji Hibernate Zadanie to:

org.apache.cxf.aegis.DatabindingException: Error writing document.. Nested exception is com.ctc.wstx.exc.WstxIOException: Invalid white space character (0x2) in text to output (in xml 1.1, could output as a character entity) 

Jak to obejść? Idealnie, mógłbym usunąć te znaki, ponieważ nie mają one znaczenia dla mojej produkcji ... Dzięki!

Odpowiedz

13
/** 
* From xml spec valid chars:<br> 
* #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]<br> 
* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF.<br> 
* @param text The String to clean 
* @param replacement The string to be substituted for each match 
* @return The resulting String 
*/ 
public static String CleanInvalidXmlChars(String text, String replacement) { 
    String re = "[^\\x09\\x0A\\x0D\\x20-\\xD7FF\\xE000-\\xFFFD\\x10000-x10FFFF]"; 
    return text.replaceAll(re, replacement); 
} 

źródło: http://www.theplancollection.com/house-plan-related-articles/hexadecimal-value-invalid-characterheplancollection.com/house-plan-related-articles/hexadecimal-value-invalid-character

+0

To całkiem blisko tego, co wtedy robiłem, więc zaznaczam to jako zaakceptowane! – elias

+0

Czy to nie jest złe? Mam na myśli, że regexp (escaped dla java) powinno być: "[^ \\ x09 \\ x0A \\ x0D \\ x20 - \\ xD7FF \\ xE000 - \\ xFFFD \\ x10000 - \\ x10FFFF]" – greguren

+0

To działa idealnie dla mnie –

7

Nie jestem pewien, czy to odpowiada na twoje pytanie, ale oto, co znalazłem.

Oto klasa, która zgłasza wyjątek: http://svn.codehaus.org/woodstox/wstx/trunk/src/java/com/ctc/wstx/api/InvalidCharHandler.java

Wydaje się, że jest dyskusja w tej sprawie tutaj: http://comments.gmane.org/gmane.comp.apache.cxf.user/4373

Może to może można: Można również ustawić " disable.outputstream.optimization "Właściwość na punkt końcowy/magistrali na wartość true, aby wyłączyć bezpośrednie zapisywanie do strumienia wyjściowego i zawsze przechodzić przez XMLStreamWriter. Powinieneś wykonać to samo, co bez kosztów związanych z utworzeniem SAAJModel.

Mam nadzieję, że to trochę pomaga.

+0

Dzięki, stary! Czytałem tę dyskusję już przed opublikowaniem tego pytania. :) Z odpowiedzi Dana Kulpa zrozumiałem, że mógłbym napisać wrapper dla XMLStreamWriter, aby zastąpić znaki, próbuję wymyślić jak to zrobić ... – elias

+0

Jeśli dobrze to rozumiem, to jest to tylko spacja? Czy mógłbyś usunąć/zastąpić go w swoim kodzie przed zapisaniem go do xml? –

+0

Aby to zrobić w moim własnym kodzie, konieczne byłoby umieszczenie wszystkich obiektów bazy danych w pamięci, aby je przetworzyć, przed wysłaniem odpowiedzi. Nie chcę tego robić z powodu niewielkiego odsetka problematycznych danych. Muszę umieścić kod, aby usunąć znaki tuż przed powiązaniem danych CXF, zapisując obiekt na wyjściu ... Czytałem dokumenty CXF, aby zobaczyć, jak to zrobić. – elias

0

Odpowiedź najwyższej klasy nie działa na mnie, jak dany kodowanie Unicode został odrzucony. Z nieznacznym zmianom Jednak wyświetlane pożądanego zachowania:

public static String CleanInvalidXmlChars(String text, String replacement) { 
    String re = "[^\\u0009\\u000A\\u000D\\u0020-\\uD7FF\\uE000-\\uFFFD\\u0001\\u0000-\\u0010\\uFFFF]"; 
    return text.replaceAll(re, replacement); 
} 
+0

To wyrażenie przyjmuje wszystkie znaki w zakresie 0x0-0x10. Większość z nich nie jest poprawna w XML. – Erik

0

do osiągnięcia pożądanego zachowania i unikania wyjątki wyrzucane, będziesz musiał przedłużyć domyślnej Woodstoks fabrykę com.ctc.wstx.stax.WstxOutputFactory własnymi tych, które miało tylko nadpisać właściwość com.ctc.wstx.outputInvalidCharHandler z instancją com.ctc.wstx.api.InvalidCharHandler.ReplacingHandler. Ten handler przyjmuje jako argument konstruktora zastępczy znak do nieważnych. Z twoją instancją, stwórz plik o nazwie META-INF/services/javax.xml.stream.XMLOutputFactory i umieść w nim tylko pełną nazwę twojej implementacji (upewnij się, że zostanie umieszczony w katalogu META-INF/services w wynikowym słoiku).

Możesz znaleźć więcej szczegółów here.

HTH!

+1

Podczas gdy ten link może odpowiedzieć na pytanie, lepiej umieścić tutaj istotne części odpowiedzi i podać link do odsyłacza. Odpowiedzi dotyczące linków mogą stać się nieprawidłowe, jeśli strona z linkami się zmieni. - [Z recenzji] (/ opinia/niskiej jakości-posts/18055529) – daniele3004

+0

Poprawiono odpowiedź odpowiednio, dzięki za wskazówki. – cristianoms