2015-06-10 3 views
5

В настоящее время я работаю с API Apache POI, и я пытаюсь редактировать документ Word с ним (*.docx). Документ состоит из абзацев (в объектах XWPFParagraph), а абзац содержит текст, встроенный в «прогоны» (XWPFRun). Параграф может иметь много запусков (в зависимости от свойств текста, но иногда это случайное). В моем документе я могу иметь определенные тег, которые мне нужно заменить данные (все мои метки следующий шаблон <#TAG_NAME#>)Получить список объектов, содержащих текст, соответствующий шаблону

Так, например, если я обрабатываю абзац, содержащий текст Some text with a tag <#SOMETAG#>, я мог бы получить что-то вроде этого

XWPFParagraph paragraph = ... // Get a paragraph from the document 
System.out.println(paragraph.getText()); 
// Prints: Some text with a tag <#SOMETAG#> 

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

System.out.println("Number of runs: " + paragraph.getRuns().size()); 
for (XWPFRun run : paragraph.getRuns()) { 
    System.out.println(run.text()); 
} 

Иногда это может быть так:

// Output: 
// Number of runs: 1 
// Some text with a tag <#SOMETAG#> 

И другое время, как этот

// Output: 
// Number of runs: 4 
// Some text with a tag 
// <# 
// SOMETAG 
// #> 

Что мне нужно сделать состоит в том, чтобы получить первый прогон, содержащий начало тега и индексы следующих прогонов, содержащих остальную часть тега (если тег делится на многие прогоны). Мне удалось получить первую версию этого алгоритма, но он работает только в том случае, если начало тега (<#) и конец тега (#>) не разделены. Here's what I've already done.

Так что я хотел бы получить алгоритм, способный управлять эту проблему и, если возможно, получить его работу с любым данным тегом (не обязательно <# и #>, так что я мог бы заменить что-то вроде этого {{{ и этого }}}).

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

+0

Можно конкатенировать все прогоны для абзаца, обновить текст, а затем заменить прогоны на один, содержащий новый текст? Может быть, вы можете заставить его работать, используя: http://stackoverflow.com/a/3638229/2611083 –

+0

Это то, что мое фактическое решение частично (если тег разделен на несколько прогонов, он объединяет текст следующих прогонов в сначала запустить и удалить их). Я не хочу конкатенировать все прогоны в первом, потому что я потеряю все текстовые параметры. Например, если абзац равен ** Данные: ** _ <#DATATAG#> _, я хочу сохранить «Данные:» жирным шрифтом и заменить данные <#DATATAG#> на данные, которые мне нужны, и сохранить их курсивом –

+0

Если весь тег имеет такие же параметры, может ли быть в разных прогонах? –

ответ

2

Наконец-то я нашел ответ сам, я полностью изменил мой образ мышления, мой оригинальный алгоритм (я прокомментировал это так, это может помочь кому-то, кто мог бы быть в той же ситуации, я был) Теперь

// Before using the function, I'm sure that: 
// paragraph.getText().contains(surroundedTag) == true 
private void editParagraphWithData(XWPFParagraph paragraph, String surroundedTag, String replacement) { 
    List<Integer> runsToRemove = new LinkedList<Integer>(); 
    StringBuilder tmpText = new StringBuilder(); 
    int runCursor = 0; 

    // Processing (in normal order) the all runs until I found my surroundedTag 
    while (!tmpText.toString().contains(surroundedTag)) { 
     tmpText.append(paragraph.getRuns().get(runCursor).text()); 
     runsToRemove.add(runCursor); 
     runCursor++; 
    } 

    tmpText = new StringBuilder(); 
    // Processing back (in reverse order) to only keep the runs I need to edit/remove 
    while (!tmpText.toString().contains(surroundedTag)) { 
     runCursor--; 
     tmpText.insert(0, paragraph.getRuns().get(runCursor).text()); 
    } 

    // Edit the first run of the tag 
    XWPFRun runToEdit = paragraph.getRuns().get(runCursor); 
    runToEdit.setText(tmpText.toString().replaceAll(surroundedTag, replacement), 0); 

    // Forget the runs I don't to remove 
    while (runCursor >= 0) { 
     runsToRemove.remove(0); 
     runCursor--; 
    } 

    // Remove the unused runs 
    Collections.reverse(runsToRemove); 
    for (Integer runToRemove : runsToRemove) { 
     paragraph.removeRun(runToRemove); 
    } 
} 

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

0

Иногда текст в файлах DOCX разбивается на произвольное количество прогонов.

Смежные вопросы