【问题标题】:Read as number codes instead of Special Characters读取为数字代码而不是特殊字符
【发布时间】:2013-10-20 08:48:03
【问题描述】:

我有一个 XML 文件可供 SAX 解析器读取,存储到 CSV 并导入数据库。

在我的 XML 文件中,有一个作者姓名:<author>Günther Heinemann</author> 如您所见,XML 中的“ü”写为&umml;

是的,我需要将作者存储在数据库中。我不能将该字符存储为“ü”。我需要将其存储为&umml;

但是当我使用 SAX 解析器从 XML 中读取数据时,它一直读取为“ü”而不是 &umml; 如何将 Java 存储为 &umml; 而不是“ü”?

谢谢

【问题讨论】:

标签: java xml database sax


【解决方案1】:

它可能也很慢,因为可能会读取包含包含的巨大 HTML DTD。 但是,您需要这样做,因为不允许使用单个 & 符号 (&)。该 HTML DTD 定义了数百个 HTML 实体名称,例如 &perc; (%)。

DTD 可以取自 XML 目录,即该 HTML URL 的离线本地版本。然后,您可以更改实体。但这工作量太大了。

可以做的是在解析器中安装你自己的EntityHandler等等。研究工作,比较轻松。

最简单的方法是将输入包装在您自己的 InputStream/Reader 中,例如用 & 替换 & 的 BufferedReader,这样就可以完成所需的替换。

在 XML 中:ü 而不是 ü

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

【讨论】:

    【解决方案2】:

    使用Apache Commons LangStringEscapeUtils实用方法escapeHtml()unescapeHtml()

    String plain = StringEscapeUtils.unescapeHtml(htmlSafe);
    
    String htmlSafe = StringEscapeUtils.escapeHtml(plain);
    

    【讨论】:

    • unescapeXml() 不做与 OP 要求相反的事情吗?我会改用escapeHtml()
    • 我自己并没有真正尝试过,但是根据文档,escapeXml()unescapeXml() 只支持五个内置的 XML 实体。为了将ü 变成ü,您似乎必须使用escapeHtml()
    • 还有一件事:在 Apache Commons Lang 的最新版本 (3.1) 中,我注意到 API 发生了一些变化。例如,escapeHtml() 已变为 escapeHtml4()
    【解决方案3】:

    您可以使用以下代码的修改版本来捕获实体的开始和结束。执行需要几秒钟,因为解析器必须获取所有 HTML latin1 实体的声明。当您获得一个不以% 开头的实体时,您可以替换acc 缓冲区中插入的字符。注意预定义的实体,例如&

    您还可以对作业自动使用 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-11-07
      • 2011-04-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多