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.