2008-09-18 27 views
27

Veritabanından çıkarılan bir XML dosyasına sahibim. XML ayrıştırmak ve farklı bir biçimde çıktılamak için Java SAX ayrıştırıcısı kullanıyorum. XML bazı geçersiz karakterler içeriyor ve ayrıştırıcı 'Geçersiz Unicode karakteri (0x5)'Java'da geçersiz XML karakterlerini sıyırma

gibi hatalar atıyor. Tüm bu karakterleri dosya satır satır ön-işleme ve değiştirmeden çıkarmanın iyi bir yolu var mı? ? Şimdiye kadar 3 farklı geçersiz karaktere (0x5, 0x6 ve 0x7) girdim. Bu bir ~ 4gb veritabanı dökümü ve biz birkaç kez işlemek için gidiyoruz, bu yüzden bir ön-işlemci çalıştırmak için yeni bir döküm almak her zaman bir ekstra 30 dakika beklemek zorunda bir acı olacak, ve bu konuya ilk defa girmedim.

Bunu şahsen kullanmadıysanız ancak Atlassian (o JIRA için esas yapıldığı ancak XML XML) cevap verecek duruma bir komut satırı XML temizleyici yapılan
+2

karakter bir anlamı var mı: –

+0

Dosya geçersiz karakterler içeriyorsa, bu bir XML dosyası değildir. İçerik oluşturucularından gelecekte yalnızca iyi oluşturulmuş XML oluşturmasını isteyin. Geçmişte bu problemi çok yaşadım. İnsanlar XML'in iyi biçimlenmiş ve çöp içermemesi gerektiğini anlamıyor gibi görünmüyor. – MarkR

+0

100% katılıyorum Ne yazık ki her zaman mümkün değil (beceriksiz teknik kişiler, sözleşmesel ifadeler, vb) – Mason

cevap

9

:

İndir atlassian-xml-cleaner-0.1.jar

Açık Bir DOS konsolu veya kabuğu bulun ve bilgisayarınızda XML veya ZIP yedek dosyasını bulun, burada data.xml olarak adlandırılmış olduğu varsayılır. Bu örnekte, data.xml

Çalıştır: java -jar atlassian-xml-cleaner-0.1.jar data.xml> data -clean.xml

Bu, data.xml dosyasının bir kopyasını data-clean.xml dosyasına yazacak ve geçersiz karakterler kaldırılacak.

+0

Bağlantı başka biri için bozuk mu? –

+0

@CyberneticTwerkGuruOrc öyle. İşte bunun için bulduğum başka bir bağlantı: https://confluence.atlassian.com/download/attachments/12079/atlassian-xml-cleaner-0.1.jar?version=1&modificationDate=1307570821061&api=v2 – cyroxx

+0

Pazar için bir eklenti oluşturuyorsanız , geçersiz karakterlerin yerini alan aynı sınıf com.atlassian.core.util.xml.XMLCleaningReader –

0

Geçersiz karakterleriniz yalnızca etiketlerin kendileri değil, yalnızca değerler içinde mevcut olabilir, yani XML şema ile bilerek değil, değerler uygun şekilde dezenfekte edilmemiş midir? Öyleyse, geçersiz karakterlerinizi XML eşdeğerleriyle değiştiren bir CleansingInputStream oluşturmak için InputStream'i geçersiz kılmaya ne dersiniz?

0

Sorununuz XML ile ilgili değil: karakter kodlamaları ile ilgilidir. Buradaki her şey, XML veya başka bir deyişle, her dizenin bayttan oluşmasıdır ve dizgiyi kodlayan karakterin size söylenmediği sürece, bu baytların hangi karakterleri temsil ettiğini bilemezsiniz. Örneğin, tedarikçi size UTF-8 olduğunu ve aslında başka bir şey olduğunu söylerse, sorun yaşamaya mecbur kalırsınız. En iyi durumda, her şey çalışır, ancak bazı baytlar 'yanlış' karakterlere çevrilir. En kötü durumda, karşılaştığınız gibi hatalar alırsınız.

Aslında, sorun daha da kötüydü: dizginiz, herhangi bir karakter kodlamasında karakterleri temsil etmeyen bayt dizileri içeriyor. Burada size yardımcı olabilecek bir XML ayrıştırıcıya izin veren hiçbir metin aracı yoktur. Bu bayt düzeyinde temizlik ihtiyacı var.

6

Ben JDK6 için beklendiği gibi iş gibi görünüyor aşağıdaki Regexp'i kullanın:

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

JDK7 yılında yerine BMP dışında yatıyor son aralığı için gösterim \x{10000}-\x{10FFFF} kullanmak mümkün olabilir Anlaşılması kolay olmayan \uD800\uDC00-\uDBFF\uDFFF notasyonu.

3

Avustralya ihracat tarifelerinin içeriğini bir XML belgesine ayrıştırırken benzer bir sorunum var. Burada önerilen çözümleri kullanamıyorum: - Komut satırından çağrılan harici bir araç (bir kavanoz) kullanın. - Avustralya Gümrüklerinin kaynak dosyayı temizlemesini isteyin.

Şu anda bu sorunu çözmek için tek yöntem, kaynak karakterin tüm içeriği boyunca karakter karakterini sınamak ve her karakterin ascii aralığı 0x00 - 0x1F'ye ait değilse, sınamaktır. Bu yapılabilir, ancak String için Java yöntemlerini kullanmanın daha iyi bir yolu olup olmadığını merak ediyordum. Kullanım Java yöntemi Dize # ReplaceAll yerine veya XML belgesinde herhangi istenmeyen karakterleri kaldırmak için:

DÜZENLEME Ben başkalarına yararlı olabilecek bir çözüm buldu.

Örnek kodu (I yığılmayı önlemek için bazı gerekli ifadeleri,): ı uzaklaştırmak Bu örnekte

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

(yani, boş bir dize değiştirmek), kapsamlı olarak 0x1F aralığında 0x00 içinde olmayan basılabilir karakter. Karakteri, uygulamanızın gerektirdiği dizeyle değiştirmek için #replaceAll() yöntemindeki ikinci bağımsız değişkeni değiştirebilirsiniz.

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(); 
} 
20

Ben Xalan org.apache.xml.utils.XMLChar sınıfı kullanılır? Muhtemelen rastgele bir yolsuzluk değiller, bu yüzden bilgi çıkarmalarını engellemiyorlar mı?
+0

adresinde yer almaktadır. Bence bu, karakter karakterleri için çalışmayacaktır: 'XMLChar # isValid()' yüksek ve düşük parçalar için yanlış döndürecektir Ayrı ayrı, ancak birlikte çift geçerli olacaksa, doğru geri döner. – ankon

İlgili konular