2

Java API を使用して xml 文字列をきれいに印刷できるようにする必要があり、Web とこの特定の Web サイトの両方で、これに対する複数のソリューションを見つけました。ただし、これを javax.xml.transform.Transformer で動作させるための複数の試みにもかかわらず、これまでのところ失敗しています。以下に示すコードは、引数の xml 文字列に xml 要素間に改行が含まれていない場合に部分的にしか機能しません。これではダメです。以前にきれいに印刷された文字列であっても、整形式で有効なxmlであると仮定して、何でもきれいに印刷できる必要があります。

私はこれを手に入れました(私が見つけたコードスニペットからまとめて、人々はそれが彼らのために働いたと主張しました):

import java.io.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;

public class XMLFormatter {

    public static String format(String xml, int indent, boolean omitXmlDeclaration)
            throws TransformerException {

        if (indent < 0) {
            throw new IllegalArgumentException();
        }
        String ret = null;
        StringReader reader = new StringReader(xml);
        StringWriter writer = new StringWriter();
        try {
            TransformerFactory factory = TransformerFactory.newInstance();
            factory.setAttribute("indent-number", new Integer(indent));
            Transformer transformer = factory.newTransformer();
            if (omitXmlDeclaration) {
                transformer.setOutputProperty(
                        OutputKeys.OMIT_XML_DECLARATION, "yes");
            }
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty(
                    "{http://xml.apache.org/xslt}indent-amount",
                    String.valueOf(indent));
            transformer.setOutputProperty(OutputKeys.METHOD, "xml");
            transformer.transform(
                    new StreamSource(reader),
                    new StreamResult(writer));
            ret = writer.toString();
        } catch (TransformerException ex) {
            throw ex;
        } finally {
            if (reader != null) {
                reader.close();
            }
            try {
                if (writer != null) {
                    writer.close();
                }
            } catch (IOException ex) {}
        }

        return ret;
    }

    public static void main(String[] args) throws TransformerException {
        StringBuilder sb = new StringBuilder();
        sb.append("<rpc-reply><data><smth/></data></rpc-reply>");

        System.out.println(sb.toString());
        System.out.println();
        System.out.println(XMLFormatter.format(sb.toString(), 4, false));

        final String NEWLINE = System.getProperty("line.separator");
        sb.setLength(0);
        sb.append("<rpc-reply>");sb.append(NEWLINE);
        sb.append("<data>");sb.append(NEWLINE);
        sb.append("<smth/>");sb.append(NEWLINE);
        sb.append("</data>");sb.append(NEWLINE);
        sb.append("</rpc-reply>");

        System.out.println(sb.toString());
        System.out.println();
        System.out.println(XMLFormatter.format(sb.toString(), 4, false));
    }
}

このコードは、これらの改行に悩まされるべきではありませんか? これはバグですか、それともここで重要な何かが欠けていますか? コード スニペットの出力:

<rpc-reply><data><smth/></data></rpc-reply>

<?xml version="1.0" encoding="UTF-8"?>
<rpc-reply>
    <data>
        <smth/>
    </data>
</rpc-reply>

<rpc-reply>
<data>
<smth/>
</data>
</rpc-reply>

<?xml version="1.0" encoding="UTF-8"?>
<rpc-reply>
<data>
<smth/>
</data>
</rpc-reply>

私が知る限り、私のコードが他の例と異なるのは、transform(in, out) メソッドに StringWriter と StringReader を使用している点だけです。私はすでにxmlをByteArrayOutputStreamに変換し、それをDOMで解析してからトランスフォーマーに供給しようとしましたが、結果は同じです。これが単一行の文字列でのみ機能する理由を知りたいです。

jdk1.6_u24 を Netbeans 6.9.1 と組み合わせて使用​​しています。

この質問は(おそらく他の多くの人にも)関連していますが、次のものと同じではありません:

JavaからXMLをきれいに印刷するには?

Transformer で XML テキストをインデントする

Transformer で作成したインデント XML

4

1 に答える 1

1

これは Transformer の正常な動作であると結論付けました。さらに。インデント機能は、それ自体ではなく、きれいなプリンターとして使用することを意図したものではありません。XML がきれいに印刷されると、(XSD、DTD、または同様のものに基づいて) ドキュメントがどのように見えるべきかを正確に知らない限り、構造が変化します。これは、どの改行文字が無視できる空白と見なされ、どれが実際の要素値またはその一部であるかを判断する唯一の方法です。Transformer は既存の空白を再フォーマットしないため、コードの出力はそのままです。

したがって、Transformer やその他のクラスを使用して、既にきれいに印刷された XML 文字列をきれいに印刷したい場合は、まず無視できる空白を取り除く必要があります。これを安全に行う唯一の方法は、XML ドキュメントの構造がどのようなものであるべきかを知ることです。 . これは現在のところ私の仮定にすぎないため、誰かにこの声明を確認してもらいたい. このステートメントが正しい場合。サードパーティのきれいなプリンターはどのように機能しますか? JTidy が XSD を必要としなかったことは知っていますが、とにかくきれいに印刷されています。テキストXMLノードに囲まれていない限り、すべての空白を無視できる空白として単に扱いますか? 無視できる空白を特定して削除する他の方法はありますか?

于 2011-08-17T07:09:56.517 に答える