2008-09-18 43 views
27

Tôi có một tệp XML là đầu ra từ cơ sở dữ liệu. Tôi đang sử dụng trình phân tích SAX Java để phân tích cú pháp XML và xuất nó theo một định dạng khác. XML có chứa một số ký tự không hợp lệ và phân tích cú pháp là ném lỗi như 'không hợp lệ Unicode ký tự (0x5)'Tước các ký tự XML không hợp lệ trong Java

Có cách nào tốt để gỡ bỏ tất cả những nhân vật này ra ngoài trước khi xử lý các tập tin line-by-line và thay thế chúng ? Cho đến nay tôi đã chạy vào 3 ký tự không hợp lệ khác nhau (0x5, 0x6 và 0x7). Đó là một kho dữ liệu ~ 4gb và chúng ta sẽ xử lý nó một loạt lần, vì vậy phải đợi thêm 30 phút mỗi lần chúng ta có một bãi chứa mới để chạy bộ xử lý trước trên nó sẽ là một cơn đau, và đây không phải là lần đầu tiên tôi gặp phải vấn đề này.

+2

Do các nhân vật có bất kỳ ý nghĩa? Có lẽ họ không phải là tham nhũng ngẫu nhiên, do đó, không tước họ loại bỏ thông tin? –

+0

Nếu tệp chứa các ký tự không hợp lệ, nó không phải là tệp XML. Yêu cầu những người sáng tạo của nó tạo ra chỉ XML được định dạng tốt trong tương lai. Tôi đã có vấn đề này rất nhiều trong quá khứ. Mọi người dường như không hiểu rằng XML cần phải được hình thành tốt và không chứa rác. – MarkR

+0

Tôi đồng ý 100% Rất tiếc, không phải lúc nào cũng có thể (những người công nghệ không đủ năng lực, từ ngữ hợp đồng, v.v.) – Mason

Trả lời

9

tôi đã không sử dụng cá nhân này nhưng Atlassian làm một XML sạch dòng lệnh mà có thể phù hợp với nhu cầu của bạn (nó đã được thực hiện chủ yếu cho JIRA nhưng XML là XML):

Tải atlassian-xml-cleaner-0.1.jar

Mở một giao diện điều khiển DOS hoặc trình bao, và định vị tệp sao lưu XML hoặc ZIP trên máy tính của bạn, ở đây được giả định được gọi là data.xml

Chạy: java -jar atlassian-xml-cleaner-0.1.jar data.xml> data -clean.xml

Thao tác này sẽ ghi một bản sao của tệp data.xml vào data-clean.xml, với các ký tự không hợp lệ bị xóa.

+0

Liên kết có bị hỏng cho bất kỳ ai khác không? –

+0

@CyberneticTwerkGuruOrc Đó là. Đây là một liên kết khác mà tôi đã tìm thấy: https://confluence.atlassian.com/download/attachments/12079/atlassian-xml-cleaner-0.1.jar?version=1&modificationDate=1307570821061&api=v2 – cyroxx

+0

Nếu xây dựng một tiện ích bổ sung cho thị trường , cùng một lớp thay thế các ký tự không hợp lệ có sẵn trên com.atlassian.core.util.xml.XMLCleaningReader –

0

Có thể các ký tự không hợp lệ của bạn chỉ có mặt trong các giá trị chứ không phải chính các thẻ đó, tức là XML đã đáp ứng hợp pháp giản đồ nhưng các giá trị chưa được vệ sinh đúng cách? Nếu vậy, điều gì về việc ghi đè InputStream để tạo ra một CleansingInputStream thay thế các ký tự không hợp lệ của bạn bằng các tương đương XML của chúng?

0

Sự cố của bạn không liên quan đến XML: nó liên quan đến mã hóa ký tự. Những gì nó đi xuống là mỗi chuỗi, có thể là XML hay cách khác, bao gồm byte và bạn không thể biết những ký tự mà các byte này đại diện, trừ khi bạn được cho biết chuỗi ký tự ký tự có. Nếu, ví dụ, nhà cung cấp cho bạn biết đó là UTF-8 và nó thực sự là một cái gì đó khác, bạn nhất định sẽ gặp phải vấn đề. Trong trường hợp tốt nhất, mọi thứ đều hoạt động, nhưng một số byte được dịch thành các ký tự 'sai'. Trong trường hợp xấu nhất, bạn nhận được lỗi như một trong những bạn gặp phải.

Thực ra, vấn đề của bạn còn tồi tệ hơn: chuỗi của bạn chứa chuỗi byte không đại diện cho các ký tự trong bất kỳ mã hóa ký tự nào. Không có công cụ texthandling, hãy để một mình một trình phân tích cú pháp XML, có thể giúp bạn ở đây. Điều này cần làm sạch mức byte.

6

tôi sử dụng regexp sau đó dường như làm việc như mong đợi cho JDK6:

Pattern INVALID_XML_CHARS = Pattern.compile("[^\\u0009\\u000A\\u000D\\u0020-\\uD7FF\\uE000-\\uFFFD\uD800\uDC00-\uDBFF\uDFFF]"); 
... 
INVALID_XML_CHARS.matcher(stringToCleanup).replaceAll(""); 

Trong JDK7 nó có thể là có thể sử dụng các ký hiệu \x{10000}-\x{10FFFF} cho phạm vi cuối cùng nằm bên ngoài của BMP thay vì \uD800\uDC00-\uDBFF\uDFFF ký hiệu không đơn giản để hiểu.

3

Tôi có vấn đề tương tự khi phân tích cú pháp nội dung của thuế xuất khẩu của Úc sang tài liệu XML. Tôi không thể sử dụng các giải pháp được đề xuất ở đây như: - Sử dụng công cụ bên ngoài (một cái bình) được gọi từ dòng lệnh. - Yêu cầu Hải quan Úc làm sạch tệp nguồn.Phương pháp duy nhất để giải quyết vấn đề này tại thời điểm này là lặp qua toàn bộ nội dung của tệp nguồn, ký tự theo ký tự và kiểm tra nếu mỗi ký tự không thuộc phạm vi từ 0x00 đến 0x1F ascii. Nó có thể được thực hiện, nhưng tôi đã tự hỏi nếu có một cách tốt hơn bằng cách sử dụng các phương thức Java cho kiểu String.

EDIT Tôi đã tìm thấy một giải pháp có thể hữu ích cho người khác: Sử dụng phương thức Java Chuỗi # ReplaceAll để thay thế hoặc xóa bất kỳ ký tự không mong muốn nào trong tài liệu XML.

Ví dụ mã (Tôi đã gỡ bỏ một số báo cáo cần thiết để tránh sự lộn xộn):

BufferedReader reader = null; 
... 
String line = reader.readLine().replaceAll("[\\x00-\\x1F]", ""); 

Trong ví dụ này tôi loại bỏ (ví dụ: thay thế bằng một chuỗi rỗng), các ký tự không thể in được trong phạm vi 0x00 đến 0x1F inclusively. Bạn có thể thay đổi đối số thứ hai trong phương thứC#replaceAll() để thay thế các ký tự bằng chuỗi mà ứng dụng của bạn yêu cầu.

20

tôi đã sử dụng Xalan org.apache.xml.utils.XMLChar lớp:

public static String stripInvalidXmlCharacters(String input) { 
    StringBuilder sb = new StringBuilder(); 
    for (int i = 0; i < input.length(); i++) { 
     char c = input.charAt(i); 
     if (XMLChar.isValid(c)) { 
      sb.append(c); 
     } 
    } 

    return sb.toString(); 
} 
+0

Tôi nghĩ cái này sẽ không hoạt động cho các ký tự thay thế: 'XMLChar # isValid()' sẽ trả về false cho các phần cao và thấp một cách riêng biệt, nhưng sẽ trả về true nếu các cặp với nhau sẽ hợp lệ. – ankon

Các vấn đề liên quan