Фильтрация недопустимых символов XML в Java - PullRequest
10 голосов
/ 24 мая 2010

Спецификация XML определяет подмножество символов Unicode, которые разрешены в документах XML: http://www.w3.org/TR/REC-xml/#charsets.

Как отфильтровать эти символы из строки в Java?

простой тестовый набор:

  Assert.equals("", filterIllegalXML(""+Character.valueOf((char) 2)))

Ответы [ 6 ]

5 голосов
/ 24 мая 2010

Найти все недопустимые символы для XML нетривиально. Вам нужно вызвать или переопределить XMLChar.isInvalid () из Xerces,

http://kickjava.com/src/org/apache/xerces/util/XMLChar.java.htm

1 голос
/ 24 мая 2010

Эта страница включает в себя метод Java для удаления недопустимых символов XML путем проверки того, соответствует ли каждый символ спецификации, хотя не рекомендуется символы

Кстати, экранирование символов не является решением, поскольку спецификации XML 1.0 и 1.1 также не допускают недопустимые символы в экранированной форме.

0 голосов
/ 10 декабря 2014

Свободно на основе комментария в ссылке из ответа Стивена С. и википедии для XML 1.1 spec вот метод java, который показывает вам, как удалить недопустимые символы с помощью регулярного выражения заменить:

boolean isAllValidXmlChars(String s) {
  // xml 1.1 spec http://en.wikipedia.org/wiki/Valid_characters_in_XML
  if (!s.matches("[\\u0001-\\uD7FF\\uE000-\uFFFD\\x{10000}-\\x{10FFFF}]")) {
    // not in valid ranges
    return false;
  }
  if (s.matches("[\\u0001-\\u0008\\u000b-\\u000c\\u000E-\\u001F\\u007F-\\u0084\\u0086-\\u009F]")) {
    // a control character
    return false;
  }

  // "Characters allowed but discouraged"
  if (s.matches(
    "[\\uFDD0-\\uFDEF\\x{1FFFE}-\\x{1FFFF}\\x{2FFFE}–\\x{2FFFF}\\x{3FFFE}–\\x{3FFFF}\\x{4FFFE}–\\x{4FFFF}\\x{5FFFE}-\\x{5FFFF}\\x{6FFFE}-\\x{6FFFF}\\x{7FFFE}-\\x{7FFFF}\\x{8FFFE}-\\x{8FFFF}\\x{9FFFE}-\\x{9FFFF}\\x{AFFFE}-\\x{AFFFF}\\x{BFFFE}-\\x{BFFFF}\\x{CFFFE}-\\x{CFFFF}\\x{DFFFE}-\\x{DFFFF}\\x{EFFFE}-\\x{EFFFF}\\x{FFFFE}-\\x{FFFFF}\\x{10FFFE}-\\x{10FFFF}]"
  )) {
    return false;
  }

  return true;
}
0 голосов
/ 29 февраля 2012

Вот решение, которое заботится о необработанном символе, а также об экранированном символе в потоке, работает со stax или sax.Это необходимо расширить для других недопустимых символов, но вы получите идею

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.io.Writer;

import org.apache.commons.io.IOUtils;
import org.apache.xerces.util.XMLChar;

public class IgnoreIllegalCharactersXmlReader extends Reader {

    private final BufferedReader underlyingReader;
    private StringBuilder buffer = new StringBuilder(4096);
    private boolean eos = false;

    public IgnoreIllegalCharactersXmlReader(final InputStream is) throws UnsupportedEncodingException {
        underlyingReader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
    }

    private void fillBuffer() throws IOException {
        final String line = underlyingReader.readLine();
        if (line == null) {
            eos = true;
            return;
        }
        buffer.append(line);
        buffer.append('\n');
    }

    @Override
    public int read(char[] cbuf, int off, int len) throws IOException {
        if(buffer.length() == 0 && eos) {
            return -1;
        }
        int satisfied = 0;
        int currentOffset = off;
        while (false == eos && buffer.length() < len) {
            fillBuffer();
        }
        while (satisfied < len && buffer.length() > 0) {
            char ch = buffer.charAt(0);
            final char nextCh = buffer.length() > 1 ? buffer.charAt(1) : '\0';
            if (ch == '&' && nextCh == '#') {
    final StringBuilder entity = new StringBuilder();
    // Since we're reading lines it's safe to assume entity is all
    // on one line so next char will/could be the hex char
    int index = 0;
    char entityCh = '\0';
    // Read whole entity
    while (entityCh != ';') {
        entityCh = buffer.charAt(index++);
        entity.append(entityCh);
    }
    // if it's bad get rid of it and clean it from the buffer and point to next valid char
    if (entity.toString().equals("&#2;")) {
        buffer.delete(0, entity.length());
        continue;
    }
            }
            if (XMLChar.isValid(ch)) {
    satisfied++;
    cbuf[currentOffset++] = ch;
            }
            buffer.deleteCharAt(0);
        }
        return satisfied;
    }

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

    public static void main(final String[] args) {
        final File file = new File(
    <XML>);
        final File outFile = new File(file.getParentFile(), file.getName()
    .replace(".xml", ".cleaned.xml"));
        Reader r = null;
        Writer w = null;
        try {
            r = new IgnoreIllegalCharactersXmlReader(new FileInputStream(file));
            w = new OutputStreamWriter(new FileOutputStream(outFile),"UTF-8");
            IOUtils.copyLarge(r, w);
            w.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(r);
            IOUtils.closeQuietly(w);
        }
    }
}
0 голосов
/ 24 мая 2010

Вы можете использовать regex (Regular Expression) для выполнения работы, см. Пример в комментариях здесь

0 голосов
/ 24 мая 2010

Использование StringEscapeUtils.escapeXml(xml) из commons-lang будет сбрасываться, а не фильтровать символы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...