Free Support Forum - aspose.com

Aspose-words, node和range无法定位到具体位置, 怎么在任意位置插入内容?

aspose-words, 我们的需求是替换word中${variable} (不能用bookmarks等)
但根据NodeType.RUN 遍历子节点的时候, 经常会有上一个node为$, 下一个是variable, 第三个是} 的情况
(我知道字体会影响node的识别,把${variable}的字体弄特殊是有用的, 不过很不灵活)
文字还好, 直接使用range.replace 即可, 但替换图片的话,range无法确定位置,documentBuilder.moveTo() 不能用, 该怎么办?
目前jar版本为 aspose-words-20.4-jdk17

@18363464070,

为了确保及时准确的响应,请ZIP并在此处附加以下资源进行测试:

  • 您的简化输入Word文档
  • Aspose.Words 20.4生成的输出DOCX文件显示了不良行为
  • 您期望的DOCX文件显示了所需的输出。 您可以使用MS Word创建此文档。
  • 还请创建一个独立的简单Java应用程序(无编译错误的源代码),以帮助我们最终重现您当前的问题并将其附加在此处进行测试。 请不要在其中包含Aspose.Words JAR文件,以减小文件大小。

在您准备好这些信息之后,我们将开始调查您的情况并为您提供更多信息。 谢谢您的合作。

你好, 不用重现吧?
打个比方, 一个word, 里面只有一行 “这是一张图片${img}”, 我想替换${img}为一张图片,
会出现一行为一个node, range里面也没有查询的方法, 只有替换的方法, 那我想插入图片的时候怎么办呢?(下面为简易 代码)
Document doc = new Document(“demo.docx”);
NodeCollection childNodes = doc.getChildNodes(NodeType.RUN, true);
for(Node node: (Iterable) childNodes) {
String trim = node.getRange().getText().trim();
System.out.println(trim);
}
//输出一行 : 这是一个图片:${IMG}, 无法准确定位位置的话, 图片插入无法定位

@18363464070,

请尝试使用以下Java代码:

Document doc = new Document("E:\\Temp\\input.docx");

Pattern pattern = Pattern.compile("\\{img}", Pattern.CASE_INSENSITIVE);
FindReplaceOptions opts = new FindReplaceOptions();
opts.setDirection(FindReplaceDirection.BACKWARD);
opts.setReplacingCallback(new ReplaceEvaluator("E:\\Temp\\Capture.PNG"));

doc.getRange().replace(pattern, "", opts);

doc.save("E:\\Temp\\awjava-20.4.docx");

static class ReplaceEvaluator implements IReplacingCallback {
    String imagePath;

    public ReplaceEvaluator(String path) {
        imagePath = path;
    }

    public int replacing(ReplacingArgs e) throws Exception {
        // This is a Run node that contains either the beginning or the complete match.
        Node currentNode = e.getMatchNode();

        // The first (and may be the only) run can contain text before the match,
        // in this case it is necessary to split the run.
        if (e.getMatchOffset() > 0)
            currentNode = splitRun((Run) currentNode, e.getMatchOffset());

        ArrayList runs = new ArrayList();

        // Find all runs that contain parts of the match string.
        int remainingLength = e.getMatch().group().length();
        while ((remainingLength > 0) && (currentNode != null) && (currentNode.getText().length() <= remainingLength)) {
            runs.add(currentNode);
            remainingLength = remainingLength - currentNode.getText().length();

            // Select the next Run node.
            // Have to loop because there could be other nodes such as BookmarkStart etc.
            do {
                currentNode = currentNode.getNextSibling();
            } while ((currentNode != null) && (currentNode.getNodeType() != NodeType.RUN));
        }

        // Split the last run that contains the match if there is any text left.
        if ((currentNode != null) && (remainingLength > 0)) {
            splitRun((Run) currentNode, remainingLength);
            runs.add(currentNode);
        }

        //// to insert Document
        DocumentBuilder builder = new DocumentBuilder((Document) e.getMatchNode().getDocument());
        builder.moveTo((Run) runs.get(runs.size() - 1));

        builder.insertImage(imagePath);

        for (Run run : (Iterable<Run>) runs)
            run.remove();

        // Signal to the replace engine to do nothing because we have already done all what we wanted.
        return ReplaceAction.SKIP;
    }

    /**
     * Splits text of the specified run into two runs. Inserts the new run just
     * after the specified run.
     */
    private Run splitRun(Run run, int position) throws Exception {
        Run afterRun = (Run) run.deepClone(true);
        afterRun.setText(run.getText().substring(position));
        run.setText(run.getText().substring((0), (0) + (position)));
        run.getParentNode().insertAfter(afterRun, run);
        return afterRun;
    }
}   

希望这可以帮助。

非常感谢, 解决我的问题

@18363464070,

感谢您的反馈意见。 如果您有其他查询或将来需要任何帮助,请告诉我们。