当前位置: 首页 > 知识库问答 >
问题:

用文本替换书签

翁阳曜
2023-03-14

我在XPages应用程序中使用docx4j创建包含XPage内容的Word文档。Word文档(.docx格式)是基于模板(.dotx格式)创建的。my.dotx模板中的一个书签如下:

<w:p>
<w:bookmarkStart w:name="Fachkompetenz" w:id="0"/>
<w:bookmarkEnd w:id="0"/>
</w:p>

使用函数

private static List<Object> getAllElementFromObject(Object obj, Class<?> toSearch) {

        List<Object> result = new ArrayList<Object>();
        if (obj instanceof JAXBElement) obj = ((JAXBElement<?>) obj).getValue();

        if (obj.getClass().equals(toSearch))
            result.add(obj); 
        else if (obj instanceof ContentAccessor) {
            List<?> children = ((ContentAccessor) obj).getContent();
            for (Object child : children) {
                result.addAll(getAllElementFromObject(child, toSearch));
            }
        }

        return result; 
    }

我可以通过调用

List<Object> texts = getAllElementFromObject(template.getMainDocumentPart(), P.class);

或CTBookmark对象调用

List<Object> texts = getAllElementFromObject(template.getMainDocumentPart(), P.class);

然而,一旦我有了这些对象,我不知道如何添加文本(XPage内容)来替换书签。我在网上尽可能多地阅读了关于这个话题的资料,但是找不到这样做的方法。有人有什么建议吗?

共有2个答案

苗冯浩
2023-03-14

我设法通过使用下面的函数解决了这个问题。将来可能需要重构,但现在它有效:

private void replaceParagraph(String placeholder, String textToAdd, WordprocessingMLPackage template) {


        List<Object> paragraphs = getAllElementFromObject(template.getMainDocumentPart(), P.class);

        for (Object p : paragraphs) {  
            RangeFinder rt = new RangeFinder("CTBookmark", "CTMarkupRange");
            new TraversalUtil(p, rt);

            for (CTBookmark content : rt.getStarts()) {  

                if (content.getName().equals(placeholder)) {  

                    List<Object> theList = null;
                    if (content.getParent() instanceof P) {
                    theList = ((ContentAccessor)(content.getParent())).getContent();
                    } else {
                    continue; 
                    }

                    if (textToAdd == ""){ 

                        int index = theList.indexOf(content);
                        Object removed = theList.remove(index);
                    } else {
                    org.docx4j.wml.R run = factory.createR();
                    org.docx4j.wml.Text t2 = factory.createText();
                    run.getContent().add(t2);   
                    t2.setValue(textToAdd);
                    theList.add(0, run); 
                    break;
                    } 
                } 
            }  

        } 

    }

杰森,谢谢你的帮助。

祁彬
2023-03-14

如果可以,您可能需要重新考虑您的方法。

由于书签是“点”标签,因此替换其内容并不容易。例如,开始标记可以位于顶级段落中,而结束标记可以位于表格单元格中!

您可能会发现内容控制数据绑定效果更好。

也就是说,假设书签的开始和结束都在一个p中(根据示例xml),可以尝试以下方法:

  1. 找到书签开始元素
  2. 使用getParent访问包含它的列表
  3. 遍历列表找到结束元素
  4. 替换2个列表条目之间的内容

在第4步,您将需要插入包含文本(w:t)的新的run (w:r)对象。您可以上传一个示例docx到docx4j webapp来生成代码。

书签替换文本.java可能会有所帮助。

 类似资料:
  • 我有一个与XPages-docx4j类似的问题,用文本替换书签,但我想保留样式。我的书签不在文本上(因为它是由Google Docs创建的docx),我想保留书签后面的文本,以便将其包含在书签中并保持其样式。例如: 我找到了删除书签后文本的解决方案,我找到了在书签内添加文本的解决方法,但我无法保留样式。 我不是以英语为母语的人,所以如果我不清楚,请毫不犹豫地问我。

  • 问题内容: 我怎样才能做到这一点? 它将替换为文本。但是我想用变量的内容替换它。 我尝试过 它也不起作用。 问题答案: 您需要使用双引号: 您的单引号可防止将shell变量替换为其内容。

  • 问题内容: 我需要从OracleSQL中的employees表中显示Employee及其佣金金额,但是条件是如果它遇到值,我需要打印_“ No Commission”_ 。 在第一部分中,我写道: 但是我无法获得如何用 “ No Commission” 代替价值观。 问题答案: 您可以使用表达式: 或: 或: PS如果不是数据类型,则也应使用或。

  • 我有一个谷歌表单,在a列中,我需要用无替换按钮上的文本。该列在几个不同的行中具有需要保持不变的标题。我写了以下脚本: 当我尝试运行脚本时,会出现以下错误:数据中的行数与范围中的行数不匹配。数据有1,但范围有2。 我知道这与具有比其他行更多列的行有关,但不确定如何修复代码。

  • 问题内容: 我有一个名为FormatString.java的文本文件。它包含一些单词。在所有这些单词中,我想将单词oldstring替换为newstring,并将最终结果重命名为t.txt。我已经编写了代码。从技术上讲,它应该起作用。问题是我不知道在哪里保存FormatString.java文件。我是否将其保存在保存了ReplacingText程序的同一类文件夹中,还是将其保存在其他地方。我转到命