Unmarshalling XML с JAXB без неэкранированных символов - PullRequest
3 голосов
/ 15 февраля 2012

представьте следующую ситуацию: мы получаем файл XML от какого-то внешнего инструмента.В последнее время в этом xml могут быть некоторые экранированные символы в именах узлов или в их теге richcontent, как в следующем примере (simplefied):

<map>
<node TEXT="Project">
<node TEXT="&#xe4;&#xe4;">
<richcontent TYPE="NOTE"><html>
  <head>

  </head>
  <body>
    <p>
      I am a Note for Node &#228;&#228;!
    </p>
  </body>
</html>
</richcontent>
</node>
</node>
</map>

После демонтажа файла с помощью JAXB эти экранированные символы не удаляются.К сожалению, мне нужно, чтобы они остались такими, какие они есть, то есть сбежали.Есть ли способ избежать удаления этих символов во время демаршаллинга?

Во время исследования я обнаружил много вопросов, касающихся маршалинга xml-файлов, где возникает противоположная проблема, но они тоже мне не помогли:

Возможно ли вообще достичь этой цели с помощью JAXB, или мы даже имеемрассмотреть возможность перехода на другой API для чтения XML?

Заранее спасибо, ymene

1 Ответ

2 голосов
/ 15 февраля 2012

Вам нужно только заменить &# на &amp;#, поэтому звоните

unmarshaller.unmarshal(new AmpersandingStream(new FileInputStream(...)));

и

import java.io.IOException;
import java.io.InputStream;

/**
* Replaces numerical entities with their notation as text.
*/
public class AmpersandingStream extends InputStream {

    private InputStream in;
    private boolean justReadAmpersand;
    private String lookAhead = "";

    public AmpersandingStream(InputStream in) {
        this.in = in;
    }

    @Override
    public int read() throws IOException {
        if (!lookAhead.isEmpty()) {
            int c = lookAhead.codePointAt(0);
            lookAhead = lookAhead.substring(Character.charCount(c));
            return c;
        }
        int c = in.read();
        if (c == (int)'#' && justReadAmpersand) {
            c = (int)'a';
            lookAhead = "mp;#";
        }
        justReadAmpersand = c == (int)'&';
        return c;
    }

    @Override
    public int available() throws IOException {
        return in.available();
    }

    @Override
    public void close() throws IOException {
        in.close();
    }

    @Override
    public synchronized void mark(int readlimit) {
        in.mark(readlimit);
    }

    @Override
    public boolean markSupported() {
        return in.markSupported();
    }

    @Override
    public int read(byte[] b) throws IOException {
        return in.read(b);
    }

    @Override
    public int read(byte[] b, int off, int len) throws IOException {
        return in.read(b, off, len);
    }

    @Override
    public synchronized void reset() throws IOException {
        in.reset();
    }

    @Override
    public long skip(long n) throws IOException {
        return in.skip(n);
    }

}
...