iText PDFSweep RegexBasedCleanupStrategy в некоторых случаях не работает

Я пытаюсь использовать iText PDFSweep RegexBasedCleanupStrategy, чтобы отредактировать некоторые слова из PDF, однако я хочу только отредактировать слово, но не появиться в другом слове, например. Я хочу редактировать "al" как отдельное слово, но я не хочу редактировать "al" в "минерале". Поэтому я добавляю границу слова ("\b") в Regex в качестве параметра для RegexBasedCleanupStrategy,

  new RegexBasedCleanupStrategy("\\bal\\b")

однако pdfAutoSweep.cleanUp не работает, если слово находится в конце строки.

1 ответ

Решение

Короче

Причиной этой проблемы является то, что процедура, которая объединяет извлеченные куски текста в единый String для применения регулярного выражения не вставляется ни один индикатор для разрыва строки. Таким образом, в этом String за последней буквой в одной строке сразу же следует первая буква следующей, которая скрывает границу слова. Можно исправить поведение, добавив соответствующий символ к String в случае разрыва строки.

Проблемный код

Процедура, которая объединяет извлеченные фрагменты текста в один String является CharacterRenderInfo.mapString(List<CharacterRenderInfo>) в упаковке com.itextpdf.kernel.pdf.canvas.parser.listener, В случае просто горизонтального промежутка эта процедура вставляет символ пробела, но в случае вертикального смещения, то есть разрыва строки, она ничего не добавляет к StringBuilder в котором String представление генерируется:

if (chunk.sameLine(lastChunk)) {
    // we only insert a blank space if the trailing character of the previous string wasn't a space, and the leading character of the current string isn't a space
    if (chunk.getLocation().isAtWordBoundary(lastChunk.getLocation()) && !chunk.getText().startsWith(" ") && !chunk.getText().endsWith(" ")) {
        sb.append(' ');
    }
    indexMap.put(sb.length(), i);
    sb.append(chunk.getText());
} else {
    indexMap.put(sb.length(), i);
    sb.append(chunk.getText());
}

Возможное исправление

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

if (chunk.sameLine(lastChunk)) {
    // we only insert a blank space if the trailing character of the previous string wasn't a space, and the leading character of the current string isn't a space
    if (chunk.getLocation().isAtWordBoundary(lastChunk.getLocation()) && !chunk.getText().startsWith(" ") && !chunk.getText().endsWith(" ")) {
        sb.append(' ');
    }
    indexMap.put(sb.length(), i);
    sb.append(chunk.getText());
} else {
    sb.append('\n');
    indexMap.put(sb.length(), i);
    sb.append(chunk.getText());
}

это CharacterRenderInfo.mapString метод вызывается только из RegexBasedLocationExtractionStrategy метод getResultantLocations() (пакет com.itextpdf.kernel.pdf.canvas.parser.listener), и только для упомянутой задачи, т.е. применения рассматриваемого регулярного выражения. Таким образом, предоставление ему возможности правильно распознавать границы слов не должно нарушать что-либо, но действительно должно рассматриваться как исправление.

Можно было бы просто добавить другой символ для разрыва строки, например, пробел ' ' если кто-то не хочет рассматривать вертикальные промежутки иначе, чем горизонтальные. Поэтому для общего исправления можно рассмотреть вопрос о том, чтобы сделать этот символ настраиваемым свойством стратегии.

Версии

Я тестировал с iText 7.1.4-SNAPSHOT и PDFSweep 2.0.3-SNAPSHOT.

Другие вопросы по тегам