XPages - docx4j - замена закладки текстом

Я использую docx4j в приложении XPages для создания документов Word, содержащих содержимое из XPage. Документ Word (в формате .docx) создается на основе шаблона (в формате .dotx). Одна закладка из моего шаблона .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; 
    }

Я могу получить объект p, позвонив

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

или вызов объекта CTBookmark

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

Однако, когда у меня есть эти объекты, я не знаю, как добавить текст (содержимое XPage), чтобы заменить закладку. Я прочитал столько, сколько я могу найти в Интернете по этой теме, но не могу найти способ сделать это. У кого-нибудь есть предложения?


person Community    schedule 28.07.2014    source источник


Ответы (2)


Если вы можете, вы можете пересмотреть свой подход.

Поскольку закладки представляют собой «точечные» теги, заменить их содержимое не так-то просто. Например, открывающий тег может находиться в абзаце верхнего уровня, а закрывающий — в ячейке таблицы!

Вы можете обнаружить, что привязка данных управления содержимым работает лучше.

Тем не менее, если предположить, что начало и конец вашей закладки находятся в одном p (согласно вашему примеру xml), вы можете попробовать следующий подход:

  1. найти начальный элемент закладки
  2. используйте getParent для доступа к списку, содержащему его
  3. перебрать список, чтобы найти конечный элемент
  4. заменить содержимое между двумя записями списка

На шаге 4 вам нужно будет вставить новые объекты запуска (w:r), содержащие текст (w:t). Вы можете загрузить образец docx в веб-приложение docx4j, чтобы сгенерировать для него код.

BookmarksReplaceWithText.java может помочь.

person JasonPlutext    schedule 28.07.2014
comment
У вас есть пример того, как я могу использовать привязку данных управления контентом? - person ; 29.07.2014
comment
Для среды выполнения см. примеры, в том числе github.com/plutext/docx4j/blob/master/src/samples/docx4j/org/ - person JasonPlutext; 29.07.2014
comment
Чтобы сэкономить время, попробуйте надстройку Word, ссылку на которую можно найти по адресу opendope.org/implementations.html. - person JasonPlutext; 29.07.2014
comment
Я просто хочу заменить закладки в шаблоне текстом при создании документа. Я предполагал, что это будет относительно просто, но, похоже, нет! Спасибо за ваши предложения, Джейсон. - person ; 29.07.2014
comment
Хорошо, если ваша закладка start и end находятся в одном p (согласно вашему примеру xml), тогда это просто. Это зависит от того, можете ли вы быть уверены, что это предположение верно. - person JasonPlutext; 29.07.2014
comment
Боюсь, я не нашел это простым. Мои закладки в том виде, в котором они были опубликованы. - person ; 29.07.2014

Мне удалось решить эту проблему, используя приведенную ниже функцию. Возможно, в будущем потребуется рефакторинг, но пока он работает:

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;
                    } 
                } 
            }  

        } 

    }

Джейсон, спасибо за помощь.

person Community    schedule 05.08.2014