26

JAXB を使用して XML にマーシャリングされているオブジェクトがあります。1 つの要素には、引用符 (") を含む文字列が含まれています。結果の XML に"は、" が存在する場所があります。

通常はこれが好まれますが、出力をレガシーシステムと一致させる必要があります。JAXB に HTML エンティティを変換させないようにするにはどうすればよいですか?

--

返信ありがとうございます。ただし、ハンドラー escape() が呼び出されることはありません。見て、私が間違っていることを確認できますか?ありがとう!

package org.dc.model;

import java.io.IOException;
import java.io.Writer;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

import org.dc.generated.Shiporder;

import com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler;

public class PleaseWork {
    public void prettyPlease() throws JAXBException {
        Shiporder shipOrder = new Shiporder();
        shipOrder.setOrderid("Order's ID");
        shipOrder.setOrderperson("The woman said, \"How ya doin & stuff?\"");

        JAXBContext context = JAXBContext.newInstance("org.dc.generated");
        Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        marshaller.setProperty(CharacterEscapeHandler.class.getName(),
                new CharacterEscapeHandler() {
                    @Override
                    public void escape(char[] ch, int start, int length,
                            boolean isAttVal, Writer out) throws IOException {
                        out.write("Called escape for characters = " + ch.toString());
                    }
                });
        marshaller.marshal(shipOrder, System.out);
    }

    public static void main(String[] args) throws Exception {
        new PleaseWork().prettyPlease();
    }
}

--

出力は次のとおりです。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<shiporder orderid="Order's ID">
    <orderperson>The woman said, &quot;How ya doin &amp; stuff?&quot;</orderperson>
</shiporder>

ご覧のとおり、コールバックは表示されません。(コールバックが呼び出されると、それが実際に自分のやりたいことを実行するか心配になります。)

--

4

14 に答える 14

13

チームメイトが見つけた解決策:

PrintWriter printWriter = new PrintWriter(new FileWriter(xmlFile));
DataWriter dataWriter = new DataWriter(printWriter, "UTF-8", DumbEscapeHandler.theInstance);
marshaller.marshal(request, dataWriter);

xmlFile を marshal() に渡す代わりに、エンコーディングと適切なエスケープ ハンドラ (存在する場合) の両方を認識している DataWriter を渡します。

注: DataWriter と DumbEscapeHandler は両方とも com.sun.xml.internal.bind.marshaller パッケージ内にあるため、javac をブートストラップする必要があります。

于 2009-10-05T21:01:57.993 に答える
4

私はあなたの例で少し遊んで、JAXB コードをデバッグしてきました。そして、使用されている UTF-8 エンコーディングに固有のもののようです。の escapeHandler プロパティがMarshallerImpl適切に設定されているようです。ただし、すべてのコンテキストで使用されているわけではありません。の呼び出しを検索すると、次のMarshallerImpl.createEscapeHandler()ことがわかりました。

public XmlOutput createWriter( OutputStream os, String encoding ) throws JAXBException {
    // UTF8XmlOutput does buffering on its own, and
    // otherwise createWriter(Writer) inserts a buffering,
    // so no point in doing a buffering here.

    if(encoding.equals("UTF-8")) {
        Encoded[] table = context.getUTF8NameTable();
        final UTF8XmlOutput out;
        if(isFormattedOutput())
            out = new IndentingUTF8XmlOutput(os,indent,table);
        else {
            if(c14nSupport)
                out = new C14nXmlOutput(os,table,context.c14nSupport);
            else
                out = new UTF8XmlOutput(os,table);
        }
        if(header!=null)
            out.setHeader(header);
        return out;
    }

    try {
        return createWriter(
            new OutputStreamWriter(os,getJavaEncoding(encoding)),
            encoding );
    } catch( UnsupportedEncodingException e ) {
        throw new MarshalException(
            Messages.UNSUPPORTED_ENCODING.format(encoding),
            e );
    }
}

(...equals("UTF-8")...)セットアップでは、上部セクションが考慮されることに注意してください。ただし、これはescapeHandler. ただし、エンコーディングを他のものに設定すると、このメソッドの下部は ( createWriter(OutputStream, String)) と呼ばれ、これは を使用するescapeHandlerため、EH がその役割を果たします。それで、追加...

    marshaller.setProperty(Marshaller.JAXB_ENCODING, "ASCII");

あなたのカスタムCharacterEscapeHandlerが呼び出されます。確かではありませんが、これは JAXB の一種のバグだと思います。

于 2009-10-06T08:19:39.303 に答える
3

@ Elliotマーシャラーが characterEscape 関数を入力できるようにするために、これを使用できます。奇妙ですが、「UTF-8」の代わりに「 Unicode 」を設定すると機能します。CharacterEscapeHandler プロパティを設定する直前または直後にこれを追加します。

marshaller.setProperty(Marshaller.JAXB_ENCODING, "Unicode");

ただし、ワークスペースのエンコーディングに応じて表示されるはずなので、IDE 内でコンソールを確認するだけでは確実ではありません。次のようなファイルからも確認することをお勧めします。

marshaller.marshal(shipOrder, new File("C:\\shipOrder.txt"));
于 2012-02-10T12:12:45.747 に答える
2

私は同じ問題を見つけました xmlWriter ファイルで xmlWriter を使用してこれを修正しました。マーシャリング中

JAXBContext jaxbContext = JAXBContext.newInstance(your class);
Marshaller marshaller = jaxbContext.createMarshaller();

marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

// Create a filter that will remove the xmlns attribute
NamespaceFilter outFilter = new NamespaceFilter(null, false);

// Do some formatting, this is obviously optional and may effect
// performance
OutputFormat format = new OutputFormat();
format.setIndent(true);
format.setNewlines(true);

// Create a new org.dom4j.io.XMLWriter that will serve as the
// ContentHandler for our filter.
XMLWriter writer = new XMLWriter(new FileOutputStream(file), format);
writer.setEscapeText(false); // <----------------- this line
// Attach the writer to the filter
outFilter.setContentHandler(writer);
// marshalling
marshaller.marshal(piaDto, outFilter);
marshaller.marshal(piaDto, System.out);

この変更writer.setEscapeText(false); 私の問題を修正しましたこれがあなたに役立つことを願っています

于 2018-01-22T07:13:59.363 に答える
1

XML仕様を確認しました。 http://www.w3.org/TR/REC-xml/#sec-referencesによると、「整形式のドキュメントでは、amp、lt、gt、apos、quot。のいずれのエンティティも宣言する必要はありません。」レガシーシステムで使用されるXMLパーサーは準拠していません。

(私はそれがあなたの問題を解決しないことを知っています、しかしどのコンポーネントが壊れているかを言うことができることは少なくとも素晴らしいです)。

于 2010-04-05T07:32:15.237 に答える
1

これは、他の投稿を読んだ後、私にとってはうまくいきます:

javax.xml.bind.JAXBContext jc = javax.xml.bind.JAXBContext.newInstance(object);
marshaller = jc.createMarshaller();         marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_ENCODING, "UTF-8");                   marshaller.setProperty(CharacterEscapeHandler.class.getName(), new CustomCharacterEscapeHandler());


public static class CustomCharacterEscapeHandler implements CharacterEscapeHandler {
        /**
         * Escape characters inside the buffer and send the output to the Writer.
         * (prevent <b> to be converted &lt;b&gt; but still ok for a<5.)
         */
        public void escape(char[] buf, int start, int len, boolean isAttValue, Writer out) throws IOException {
            if (buf != null){
                StringBuilder sb = new StringBuilder();
                for (int i = start; i < start + len; i++) {
                    char ch = buf[i];

                    //by adding these, it prevent the problem happened when unmarshalling
                    if (ch == '&') {
                        sb.append("&amp;");
                        continue;
                    }

                    if (ch == '"' && isAttValue) {
                        sb.append("&quot;");
                        continue;
                    }

                    if (ch == '\'' && isAttValue) {
                        sb.append("&apos;");
                        continue;
                    }


                    // otherwise print normally
                    sb.append(ch);
                }

                //Make corrections of unintended changes
                String st = sb.toString();

                st = st.replace("&amp;quot;", "&quot;")
                       .replace("&amp;lt;", "&lt;")
                       .replace("&amp;gt;", "&gt;")
                       .replace("&amp;apos;", "&apos;")
                       .replace("&amp;amp;", "&amp;");

                out.write(st);
            }
        }
    }
于 2014-01-27T14:38:05.250 に答える
1

私は自分でやったことがありませんが、Sun の JAXB 実装では可能のようです。

于 2009-10-01T23:29:37.167 に答える
0

面白いですが、文字列を使って試すことができます

Marshaller marshaller = jaxbContext.createMarshaller();
StringWriter sw = new StringWriter();
marshaller.marshal(data, sw);
sw.toString();

少なくとも私にとっては、これは引用符をエスケープしないでください

于 2011-03-07T15:14:54.870 に答える
0

なんらかの理由で調べる時間がないので、設定時にうまくいきました

marshaller.setProperty(Marshaller.JAXB_ENCODING, "utf-8");

"UTF-8"またはを使用するのとは対照的に"Unicode"

それらを試してみることをお勧めします. @Javatarが言ったように、次を使用してファイルへのダンプを確認してください。

marshaller.marshal(shipOrder, new File("<test_file_path>"));

notepad ++のような適切なテキストエディターで開きます

于 2014-03-31T07:50:17.860 に答える
0

Sun の Marshaller 実装を使用する場合の最も簡単な方法は、何もエスケープしない CharacterEscapeEncoder の独自の実装を提供することです。

    Marshaller m = jcb.createMarshaller();
m.setProperty(
    "com.sun.xml.bind.marshaller.CharacterEscapeHandler",
    new NullCharacterEscapeHandler());

public class NullCharacterEscapeHandler implements CharacterEscapeHandler {

    public NullCharacterEscapeHandler() {
        super();
    }


    public void escape(char[] ch, int start, int length, boolean isAttVal, Writer writer) throws IOException {
        writer.write( ch, start, length );
    }
}
于 2011-08-03T22:10:53.487 に答える