LINUX.ORG.RU

чем разобрать odt?

 ,


1

1

ну чтоб на яве.

Apache ODFDOM не нравится тем, что он не все разбирает. например если есть нумерованный список, то апачий getTextContent берет и склеивает элементы списка без разделителей. при этом тот же libreoffice все открывает корректно.

и вообще она с 11-го года вроде как не обновляется..?

бороться с либой --- это конечно да, но я бы предпочел подоткнуть другую. хочу просто получить текст из документа.

Ответ на: комментарий от Rastafarra

У LibreOffice есть какая-то консольная «база»? Может libreoffice-core это и есть то самое минимальное, что можно дергать через их API?

I-Love-Microsoft ★★★★★
()

А в Tika что сейчас используется?

maxcom ★★★★★
()

поборол вот так:

    private static String getTextFromNode (Node node) {
        return
            IntStream
                .range(0, node.getChildNodes().getLength())
                .mapToObj((int idx) -> {
                    if (node.getChildNodes().getLength() > 1)
                        return getTextFromNode(node.getChildNodes().item(idx));
                    else
                        return node.getTextContent();
                })
                .collect(Collectors.joining(" "));
    }
Rastafarra ★★★★
() автор топика
Ответ на: комментарий от Rastafarra

В зависимости от того, что тебе нужно, и документы какой сложности ты анализируешь, есть ещё вариант разархивировать odt и напрямую разбирать нижележащий XML. У odt довольно понятная простым смертным структура (по крайней мере, в случае простых документов), и вытянуть текст не составит особого труда. Хочу, правда предупредить, что у него есть привычка оборачивать <elem>отдельные куски текста в дополнительные тэги</elem> без особых на то причин, поэтому тут нужно быть внимательным при разборе XML.

runtime ★★★★
()
Ответ на: комментарий от Rastafarra

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

А так - да, хозяин-барин.

anonymous
()
Ответ на: комментарий от Rastafarra

Дополню: Если задача строго стоит ограничиться ODT, парсить руками XML однозначно проще. Если же в перспективе надо будет добавить к понимаемым форматам docx, rtf или (чур меня, чур меня!) doc от Word 2003, то таки библиотека.

anonymous
()
Ответ на: комментарий от anonymous

парсить руками XML однозначно проще.

ну мое решение я показал выше, опустив всякие Files.readAllBytes.

покажи класс, распарси xml руками :)

Rastafarra ★★★★
() автор топика
Ответ на: комментарий от I-Love-Microsoft

Можно написать макрос на одном из встроенных в LibreOffice языков (как минимум это Basic и Python), который будет делать то, что тебе нужно. Макросы умеют:

1) Заставлять LibreOffice открывать/закрывать документы, получать доступ к содержимому документа.

2) Работать с внешними файлами. В смысле там есть команды для открытия файлов и чтения/записи туда.

Таким образом можно написать некий конвертер, который будет в автоматическом режиме грузить документ, выделять оттуда всё нужное и сохранять в текстовый файл в нужном тебе формате. Да, список файлов для обработки тоже можно прочитать из текстового файла. Также вроде как можно сделать так, чтобы при открытии документа автоматически запустился указанный макрос. Соответственно, задача сводится к тому, чтобы запустить LibreOffice, передав ему в качестве аргумента командной строки путь к файлу со встроенным твоим макросом, а потом забрать созданные им файлы.

Минусы - это не самый оптимальный вариант (придётся запускать целый офисный пакет) + нужны иксы.

KivApple ★★★★★
()
Ответ на: комментарий от KivApple

+ нужны иксы

Когда-то я пытался чето делать через скрипт на Python + LibreOffice (PyUno), вроде графические программы не запускались. Откуда инфа про иксы, headless оно не может?

I-Love-Microsoft ★★★★★
()
Ответ на: комментарий от I-Love-Microsoft

Я не знаю. Я просто предложил вариант вообще использовать встроенный макроязык LibreOffice.

KivApple ★★★★★
()
Ответ на: комментарий от Deleted
    private static String getTextFromNode (Node node) {
        NodeList childs = node.getChildNodes();
        Integer childCount = childs.getLength();
        return
            IntStream
                .range(0, childCount)
                .mapToObj((int idx) -> {
                    if (childCount > 1)
                        return getTextFromNode(childs.item(idx));
                    else
                        return node.getTextContent();
                })
                .collect(Collectors.joining(" "));
    }

пусть мне стало стыдно :)

Rastafarra ★★★★
() автор топика
Последнее исправление: Rastafarra (всего исправлений: 1)
Ответ на: комментарий от Rastafarra

бритвой оккама, у тебя банальный цикл, который даже не нужен если childCount == 1, а ты еще суешь if унутыль лямбды, прямо мастер обфускации.

Стримы худо-бедно имеет смысл юзать когда у тебя удобно использовать ссылки функции:

return
            IntStream
                .range(0, childCount)
                .mapToObj(childs::item))
                .map(this::getTextFromNode)   
                .collect(Collectors.joining(" "));

но тогда надо вынести if, а если просто использовать for(int i = 0; ... - то оно будет еще и понятнее, и со временем ты дойдешь до мысли, что можно использовать StringBuilder предавая его в getTextFromNode - что на больших документах даст заметную экономию. Ну и потом может потребуется скипать пустые строки и т.п.

Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.