2015-06-10 33 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

这就是我的实际解决方案部分(如果标签被分成多次运行,它将以下运行的文本连接在首先运行并删除它们)。我不想连接第一个中的所有运行,因为我将丢失所有文本参数。 例如,如果该段落是** Data:** _ <#DATATAG#> _,我希望保留“Data:”以粗体显示,并用我需要的数据替换<#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文件中的文本会被分解为任意数量的运行。

相关问题