1

複数のxmlファイルを読み込んで、そこから1つのモデルを作成する必要がある状況があります。悲しいことに、ファイルは私が絶対に変更できないレガシーシステムによって生成されます。

問題を引き起こしているXMLファイルの1つは、多かれ少なかれ次のようになります(独自のデータを削除するように変更されています)。

<resource lang="en" dataId="900">
 numbered content here, 900-919 ...

    <string name="920-name">Document Shredder</string>
    <string name="920-desc">A machine ideal for destroying documents that deserve it. It can cross-shred anything from tissue paper to small netbooks with minimal noise. Remember, hackers can't access the documents if you've shredded the drives.</string>
    <string name="920-cat">office,appliance</string>
    <string name="921-name">Plastic Ladle</string>
    <string name="921-desc">This is a big plastic ladle, ideal for soups and sauces.</string>
    <string name="921-cat">kitchen,utensils</string>

... similar numbered content here, 922-934 ...

    <string name="935-name">Green Laser Pointer</string>
    <string name="935-desc">A High-Powered green laser pointer, ideal for irritating cats.</string>
    <string name="935-cat">office,tool</string>
    <string name="936-name">Black Metal Filing Cabinet</string>
    <string name="936-desc">A large, metal cabinet (black) built to store hanging file folders.</string>
    <string name="936-cat">office,storage</string>

... similar numbered content here, 937-994
</resource>

これを解析してList<CString>、ここで、CString.javaは次のとおりです。

public class CString {
    public String name;
    public String desc;

    @Override
    public String toString() {
        return "CString {!name: " + name + " !body: " + body + "}\n";
    }
}

私はを使用してみましたがDocumentBuilder、それが正しく機能しなかった場合は、単なるプレーンSaxParserです。ただし、どのように処理しても、CStringsに戻ると、本文にドキュメントのさまざまな部分の未解析のタグが実際に含まれている場所がいくつかあります。たとえば、前述の内容を印刷すると、次のList<CString>ようになります。

[ CStrings for 900-919 ...

, CString {!name: 920-name !body: Document Shredder}
, CString {!name: 920-desc !body: irritating cats.</string>
    <string name="935-cat">office,tool</string>
    <string name="936-name">Black Metal Filing Cabinet</e. Remember, hackers can't access the documents if you've shredded the drives.}
, CString {!name: 920-cat !body: office,appliance}
, CString {!name: 921-name !body: Plastic Ladle}
, CString {!name: 921-desc !body: This is a big plastic ladle, ideal for soups and sauces.}
, CString {!name: 921-cat !body: kitchen,utensils}

... CStrings for 922-934 ... 

, CString {!name: 935-name !body: Green Laser Pointer}
, CString {!name: 935-desc !body: A High-Powered green laser pointer, ideal for irritating cats.}
, CString {!name: 935-cat !body: office,tool}
, CString {!name: 936-name !body: Black Metal Filing Cabinet}
, CString {!name: 936-desc !body: A large, metal cabinet (black) built to store hanging file folders.}
, CString {!name: 936-cat !body: office,storage}

... CStrings for 937-994
]

SaxParser私のコードのバージョンでは、次のcharactersメソッドがありましたDefaultHandler

public void characters(char ch[], int start, int length) throws SAXException {
    String value = new String(ch, start, length).trim();
    switch(currentQName.toString()) { // currentQName is a StringBuilder that holds just the current xml element's name
        case "string":
            if (value.contains("</string")) {
                System.err.println("!!! Parse Error !!! " + value);
            }
}

ご想像のとおり、これは次のようになります。

!!! Parse Error !!! irritating cats.</string>
        <string name="935-cat">office,tool</string>
        <string name="936-name">Black Metal Filing Cabinet</e. Remember, hackers can't access the documents if you've shredded the drives.

特に具体的なデータとコードを提供できない場合、私は通常、この難解な質問をしませんが、グーグルの量は私が特定できたものを何ももたらさないようです、そしてもちろんコードはそうではありません例外をスロー(または抑制)します。

私が気づいたことの1つは、上記の920-descのCStringに見られるように、間違ったデータがある場合、この場合の間違ったデータは138文字の長さであり、偶然ではありませんが、適切なデータは正確に139文字を取得します。する必要があります。これは、ある種のバッファの問題だと思います。ただし、バッファの管理を許可する場合でもDocumentBuilder、ストレートを使用して手動でバッファを管理する場合SaxParserでも、毎回同じ場所でまったく同じ間違ったテキストが表示されます。最後に、短い文字列、name、catを処理するときに、間違ったテキストに気付くことはありません。これは、charバッファの問題も示していると思います。

どんなアイデアも役に立ちます!

4

2 に答える 2

0

コード内で、特殊文字が不必要にクリーンアップされている場所を見つけました(ソースからのフォーマットが不十分な以前の問題と戦うためだと思います)。

以前にすべてのストリッピングを実行したメソッドは次のとおりです。

private static InputSource getCleanSource(File file) {
    InputSource source = null;
    try {
        InputStream stream = new FileInputStream(file);
        String fileText = readFile(stream); // Gets file content as text from InputStream

        CharsetDecoder utf8Decoder = Charset.forName("UTF-8").newDecoder();
        utf8Decoder.onMalformedInput(CodingErrorAction.IGNORE);
        utf8Decoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
        CharBuffer parsed = utf8Decoder.decode(ByteBuffer.wrap(readFile(stream).getBytes()));

        fileText = "<?xml version=\"1.1\" encoding=\"UTF-8\" ?>\n" + // put a good header
                parsed
                .replaceAll("<\\?.*?\\?>", "") // remove bad <?xml> tags
                .replaceAll("--+","--") // can't have <!--- text --->
                .replaceFirst("(?s)^.+?<\\?", "<?") // remove bad stuff before <?xml> tag
                .replaceAll("[^\\x20-\\x7e\\x0A]", "") // remove bad characters
                .replaceAll("[\\x0A]", " ") // remove line breaks
                ;
        Reader reader = new StringReader(fileText);
        source = new InputSource(reader);
    } catch (Throwable t) {
        System.err.println("Unknown trouble parsing: " + file.getName());
        t.printStackTrace();
    }

    return source;
}

これを確認して調整した後、このメソッドを次のように変更すると、すべてが正常に機能します。

private static InputSource getCleanSource(File file) {
    InputSource source = null;
    try {
        InputStream stream = new FileInputStream(file);
        String fileText = readFile(stream) // Gets file content as text from InputStream
                .replaceAll("--+","--") // can't have <!--- text --->
                .replaceFirst("(?s)^.+?<\\?", "<?") // remove bad stuff before <?xml> tag
                ;
        Reader reader = new StringReader(fileText);
        source = new InputSource(reader);
    } catch (Throwable t) {
        System.err.println("Unknown trouble parsing: " + file.getName());
        t.printStackTrace();
    }

    return source;
}

私はまだ戻って、掃除の過程でどんな謎のキャラクターやタグが食べ尽くされているのかを理解しようとする時間がありませんでした。ソースシステムは元々、そのような積極的なクリーニングに値する現在よりもはるかに有効性の低いxmlを提供したと想定する必要がありますが、確実にわかるとは思いません。

于 2013-01-28T20:27:57.583 に答える
0

ほぼ確実に、整形式のXMLはありません(ソースシステムの変更が絶対に許可されていないというコメントは悪い兆候ですが、その苦境にいるのはあなただけではありません)。

この質問を見てくださいJavaで不正に形成されたXMLを解析する方法は?

私があなたなら、生の文字列操作や正規表現を使用して、データを直接抽出するか、整形式のXMLに修正します。ちなみに、JAXBはJavaでXMLを処理するのにはるかに優れています(ただし、それでも整形式である必要があります)

于 2013-01-15T22:47:24.913 に答える