Читайте XHTML и пользовательские теги в дереве DOM - PullRequest
4 голосов
/ 19 августа 2011

Я делаю преобразование из XHTML в PDF, используя летающую тарелку, она отлично работает, но теперь я хочу добавить закладки, и согласно документации fs это должно быть сделано так:

<bookmarks>
    <bookmark name='1. Foo bar baz' href='#1'>
      <bookmark name='1.1 Baz quux' href='#1.2'>
      </bookmark>
    </bookmark>
    <bookmark name='2. Foo bar baz' href='#2'>
      <bookmark name='2.1 Baz quux' href='#2.2'>
      </bookmark>
    </bookmark>
</bookmarks>

Это должно быть помещено в раздел HEAD, я сделал это, но SAXParser больше не будет читать файл, говоря:

line 11 column 14 - Error: <bookmarks> is not recognized!
line 11 column 25 - Error: <bookmark> is not recognized!

У меня настроен локальный преобразователь сущностей, и я даже добавил закладки в DTD,

<!--flying saucer bookmarks -->
<!ELEMENT bookmarks (#PCDATA)>
<!ATTLIST bookmarks %attrs;>

<!ELEMENT bookmark (#PCDATA)>
<!ATTLIST bookmark %attrs;>

Но это не парсинг, у меня нет идей, пожалуйста, помогите.

EDIT

Я использую следующий код для разбора:

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dbf.newDocumentBuilder();
builder.setEntityResolver(new LocalEntityResolver());
document = builder.parse(is);

EDIT

Вот LocalEntityResolver:

 class LocalEntityResolver implements EntityResolver {

    private static final Logger LOG = ESAPI.getLogger(LocalEntityResolver.class);
    private static final Map<String, String> DTDS;
    static {
        DTDS = new HashMap<String, String>();
        DTDS.put("-//W3C//DTD XHTML 1.0 Strict//EN",
                "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd");
        DTDS.put("-//W3C//DTD XHTML 1.0 Transitional//EN",
                "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd");
        DTDS.put("-//W3C//ENTITIES Latin 1 for XHTML//EN",
                "http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent");
        DTDS.put("-//W3C//ENTITIES Symbols for XHTML//EN",
                "http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent");
        DTDS.put("-//W3C//ENTITIES Special for XHTML//EN",
                "http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent");
    }

    @Override
    public InputSource resolveEntity(String publicId, String systemId)
            throws SAXException, IOException {
        InputSource input_source = null;
        if (publicId != null && DTDS.containsKey(publicId)) {
            LOG.debug(Logger.EVENT_SUCCESS, "Looking for local copy of [" + publicId + "]");

            final String dtd_system_id = DTDS.get(publicId);
            final String file_name = dtd_system_id.substring(
                    dtd_system_id.lastIndexOf('/') + 1, dtd_system_id.length());

            InputStream input_stream = FileUtil.readStreamFromClasspath(
                    file_name, "my/class/path",
                    getClass().getClassLoader());
            if (input_stream != null) {
                LOG.debug(Logger.EVENT_SUCCESS, "Found local file [" + file_name + "]!");
                input_source = new InputSource(input_stream);
            }
        }

        return input_source;
    }
}

Моя реализация фабрики по созданию документов: com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl

1 Ответ

0 голосов
/ 22 августа 2011

Тьфу, я наконец нашел проблему. Извините за то, что вы, ребята, сделали отладку кода, проблема заключалась в том, что в моем коде был вызов JTidy.parse непосредственно перед синтаксическим анализом DOM, в результате чего содержимое было проанализировано, чтобы быть пустым, и я даже не уловил этого, Фактическая ошибка была Premature End of file от SAX.

Благодаря Мэтту Гибсону, когда я просматривал код для составления короткого входного документа, я обнаружил ошибку.

Мой код теперь включает проверку, чтобы видеть, было ли содержимое нулевым

/**
 * parses String content into a valid XML document.
 * @param content the content to be parsed.
 * @return the parsed document or <tt>null</tt>
 */
private static Document parse(final String content) {
    Document document = null;
    try {
        if (StringUtil.isNull(content)) {
            throw new IllegalArgumentException("cannot parse null "
                    + "content into a DOM object!");
        }

        InputStream is = new ByteArrayInputStream(content
                .getBytes(CONTEXT.getEncoding()));

        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = dbf.newDocumentBuilder();
        builder.setEntityResolver(new LocalEntityResolver());
        document = builder.parse(is);
    } catch (Exception ex) {
        LOG.error(Logger.EVENT_FAILURE, "parsing failed "
                + "for content[" + content + "]", ex);
    }

    return document;
}
...