Читать как числовые коды вместо специальных символов

У меня есть файл XML, который должен быть прочитан синтаксическим анализатором SAX, сохранен в CSV и импортирован в базу данных.

В моем файле XML есть Автор с именем: <author>G&uuml;nther Heinemann</author> Как видите, «ü» в XML записывается как &umml;.

ТАК да, мне нужно сохранить автора в базе данных. Я не могу сохранить этот символ как «ü». Мне нужно сохранить его как &umml;

Но когда я использую синтаксический анализатор SAX для чтения из XML, он продолжает читать как «ü» вместо &umml;. Как я могу сохранить Java как &umml;, а не «ü»?

Спасибо


person user2741620    schedule 12.10.2013    source источник
comment
возможный дубликат парсера SAX: игнорирование специальных символов   -  person Ludovic Kuty    schedule 25.10.2013


Ответы (3)


Вероятно, это тоже медленно, так как, вероятно, читается огромный HTML DTD с включениями. Однако вам это нужно, так как один амперсанд (&) не разрешен. Это HTML DTD определяет сотни имен объектов HTML, таких как &perc; (%).

DTD можно взять из XML-каталога, который является автономной локальной версией для этого URL-адреса HTML. Затем вы можете изменить сущности. Но это слишком много работы.

Что можно сделать, так это установить свой собственный EntityHandler в парсер и так далее. Исследовательская работа, относительно легкая.

Проще всего было бы обернуть ввод в свой собственный InputStream/Reader, скажем, в BufferedReader, заменив & на &amp;, что сделает необходимые замены.

В XML: &amp;uuml; вместо &uuml;.

line = line.replace("&", "&amp;");
// Undo XML escapes:
String[] xmlTags = { "amp", "lt", "gt", "quot", "apos" };
for (String xmlTag : xmlTags) {
    line = line.replace("&amp;" + xmlTag + ";", "&" + xmlTag + ";");
}
person Joop Eggen    schedule 12.10.2013

Используйте Apache Commons Lang StringEscapeUtils служебные методы escapeHtml() и unescapeHtml()

String plain = StringEscapeUtils.unescapeHtml(htmlSafe);

String htmlSafe = StringEscapeUtils.escapeHtml(plain);
person Bohemian♦    schedule 12.10.2013
comment
Разве unescapeXml() не делает противоположное тому, о чем просит ОП? Я бы попробовал escapeHtml() вместо этого. - person mzjn; 12.10.2013
comment
На самом деле я сам ничего из этого не пробовал, но, согласно документации, escapeXml() и unescapeXml() поддерживают только пять встроенных объектов XML. Чтобы превратить ü в &uuml;, кажется, вам придется использовать escapeHtml(). - person mzjn; 12.10.2013
comment
Еще один момент: в последней версии (3.1) Apache Commons Lang я заметил некоторые изменения в API. Например, escapeHtml() стал escapeHtml4(). - person mzjn; 13.10.2013

Вы можете использовать модифицированную версию приведенного ниже кода, которая улавливает начало и конец сущностей. Выполнение занимает несколько секунд, так как синтаксический анализатор должен получить объявления всех сущностей HTML latin1. Когда вы получаете объект, который не начинается с %, вы можете заменить вставленный символ в свой буфер acc. Обратите внимание на предопределенные объекты, такие как &amp;.

Вы также можете автоматически использовать фильтр Sax для задания. Ср. ответ https://stackoverflow.com/a/5524862/452614. Я мог бы обновить свой ответ, чтобы предоставить полное решение.

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.*;
import org.xml.sax.ext.DefaultHandler2;

class MyHandler extends DefaultHandler2 {

    private StringBuilder acc;

    public MyHandler() {
        acc = new StringBuilder();
    }

    @Override
    public void startElement(String uri, String localName, String qName,
            Attributes atts) throws SAXException {
        System.out.printf("startElement. uri:%s, localName:%s, qName:%s\n", uri,     localName, qName);
        acc.setLength(0);
    }

    @Override
    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        System.out.printf("endElement. uri:%s, localName:%s, qName:%s\n", uri,     localName, qName);
        System.out.printf("Characters accumulated: %s\n", acc.toString());
        acc.setLength(0);
    }

    @Override
    public void characters(char[] ch, int start, int length)
            throws SAXException {
        acc.append(ch, start, length);
        System.out.printf("characters. [%s]\n", new String(ch, start, length));
    }

    @Override
    public void startEntity(java.lang.String name)
            throws SAXException {
        System.out.printf("startEntity: %s\n", name);
    }

    @Override
    public void endEntity(java.lang.String name)
            throws SAXException {
        System.out.printf("endEntity: %s\n", name);
    }
}

public class SAXTest1 {

    public static void main(String args[]) throws SAXException,     ParserConfigurationException, UnsupportedEncodingException {
        String s = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE author [\n<    !ELEMENT author (#PCDATA)>\n<!ENTITY % HTMLlat1 PUBLIC \"-//W3C//ENTITIES     Latin 1 for XHTML//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent\">    \n%HTMLlat1;\n]>\n<author>G&uuml;nther Heinemann</author>";
        System.out.println(s);
        InputStream stream = new ByteArrayInputStream(s.getBytes("UTF-8"));

        SAXParserFactory factory = SAXParserFactory.newInstance();
        factory.setValidating(true);
        XMLReader xmlReader = factory.newSAXParser().getXMLReader();

        DefaultHandler2 handler = new MyHandler();
        xmlReader.setContentHandler(handler);
        xmlReader.setProperty(
                "http://xml.org/sax/properties/lexical-handler",
                handler);

        try {
            xmlReader.parse(new InputSource(stream));
        } catch (IOException e) {
            System.err.println("I/O error: " + e.getMessage());
        } catch (SAXException e) {
            System.err.println("Parsing error: " + e.getMessage());
        }
    }
}

Выполнение программы:

$ java SAXTest1
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE author [
<!ELEMENT author (#PCDATA)>
<!ENTITY % HTMLlat1 PUBLIC "-//W3C//ENTITIES Latin 1 for XHTML//EN" "http://www.w3.    org/TR/xhtml1/DTD/xhtml-lat1.ent">
%HTMLlat1;
]>
<author>G&uuml;nther Heinemann</author>
startEntity: %HTMLlat1
endEntity: %HTMLlat1
startElement. uri:, localName:, qName:author
characters. [G]
startEntity: uuml
endEntity: uuml
characters. [ünther Heinemann]
endElement. uri:, localName:, qName:author
Characters accumulated: Günther Heinemann
person Ludovic Kuty    schedule 25.10.2013