获取包含与模式匹配的文本的对象列表
Get the list of object containing text matching a pattern
我目前正在使用 API Apache POI,我正在尝试用它编辑 Word 文档 (*.docx
)。文档由段落组成(在 XWPFParagraph
个对象中),一个段落包含嵌入在 'runs' (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#>
但是如果我想编辑那个段落的文本我需要处理运行s并且运行s的数量是不固定的。因此,如果我使用该代码显示 运行s 的内容:
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.
所以我想得到的是一个能够解决这个问题的算法,如果可能的话让它与任何给定的标签一起工作(不一定是 <#
和 #>
,所以我可以用像这个 {{{
和这个 }}}
).
抱歉,如果我的英语不完美,请随时让我澄清您想要的任何一点。
最后我自己找到了答案,我完全改变了我对原始算法的思考方式(我对其进行了评论,以便它可以帮助可能与我处于相同情况的人)
// 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);
}
}
所以现在我正在处理该段落的所有运行,直到找到我包围的标签,然后我正在处理该段落以忽略第一运行,如果我不需要编辑它们的话。
我目前正在使用 API Apache POI,我正在尝试用它编辑 Word 文档 (*.docx
)。文档由段落组成(在 XWPFParagraph
个对象中),一个段落包含嵌入在 'runs' (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#>
但是如果我想编辑那个段落的文本我需要处理运行s并且运行s的数量是不固定的。因此,如果我使用该代码显示 运行s 的内容:
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.
所以我想得到的是一个能够解决这个问题的算法,如果可能的话让它与任何给定的标签一起工作(不一定是 <#
和 #>
,所以我可以用像这个 {{{
和这个 }}}
).
抱歉,如果我的英语不完美,请随时让我澄清您想要的任何一点。
最后我自己找到了答案,我完全改变了我对原始算法的思考方式(我对其进行了评论,以便它可以帮助可能与我处于相同情况的人)
// 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);
}
}
所以现在我正在处理该段落的所有运行,直到找到我包围的标签,然后我正在处理该段落以忽略第一运行,如果我不需要编辑它们的话。