Docx4J не заменяет заполнители

Я пытаюсь заменить простой «Place Holderin MS Word 2007 usingDocx4J. I created the placeholder byReference > Insert Citation > Add New Placeholder»

Ниже мой код Docx4J

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.JAXBElement;
import org.docx4j.openpackaging.exceptions.Docx4JException;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.wml.ContentAccessor;
import org.docx4j.wml.Text;

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
/**
 *
 * @author Yohan
 */
public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        new Main();
    }
    public Main()
    {
        try
        {
            WordprocessingMLPackage template = getTemplate("C:/Users/Yohan/Desktop/Yohan.docx");
            replacePlaceholder(template,"Plane","Placeholder1");
            writeDocxToStream(template,"C:/Users/Yohan/Desktop/Yohan2.docx");

            System.out.println("Operation Completed");
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }



    private WordprocessingMLPackage getTemplate(String name) throws Docx4JException, FileNotFoundException {
        WordprocessingMLPackage template = WordprocessingMLPackage.load(new FileInputStream(new File(name)));
        return template;
    }

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

        private void replacePlaceholder(WordprocessingMLPackage template, String name, String placeholder ) {
        List<Object> texts = getAllElementFromObject(template.getMainDocumentPart(), Text.class);

        for (Object text : texts) {
            Text textElement = (Text) text;
            if (textElement.getValue().equals(placeholder)) {
                textElement.setValue(name);
            }
        }
    }



    private void writeDocxToStream(WordprocessingMLPackage template, String target) throws IOException, Docx4JException {
        File f = new File(target);
        template.save(f);
    }

}

Это сгенерировало ниже в консоли Netbeans.

[main] INFO org.docx4j.jaxb.Context - java.vendor=Oracle Corporation
[main] INFO org.docx4j.jaxb.Context - java.version=1.8.0_05
[main] INFO org.docx4j.jaxb.Context - No MOXy JAXB config found; assume not intended..
[main] INFO org.docx4j.jaxb.NamespacePrefixMapperUtils - Using NamespacePrefixMapperSunInternal, which is suitable for Java 6
[main] INFO org.docx4j.jaxb.Context - Using Java 6/7 JAXB implementation
[main] INFO org.docx4j.jaxb.Context - Not using MOXy; using com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl
[main] WARN org.docx4j.utils.ResourceUtils - Couldn't get resource: docx4j.properties
[main] WARN org.docx4j.Docx4jProperties - Couldn't find/read docx4j.properties; docx4j.properties not found via classloader.
[main] INFO org.docx4j.XmlUtils - Using com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl
[main] INFO org.docx4j.XmlUtils - Using com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl
[main] INFO org.docx4j.openpackaging.contenttype.ContentTypeManager - Detected WordProcessingML package 
[main] INFO org.docx4j.openpackaging.io3.Load3 - Instantiated package of type org.docx4j.openpackaging.packages.WordprocessingMLPackage
[main] INFO org.docx4j.utils.XPathFactoryUtil - xpath implementation: org.apache.xpath.jaxp.XPathFactoryImpl
[main] INFO org.docx4j.openpackaging.io.Load - Found a CustomXmlPart, named /customXml/item1.xml
[main] INFO org.docx4j.openpackaging.parts.JaxbXmlPart - Lazily unmarshalling /customXml/itemProps1.xml
[main] INFO org.docx4j.openpackaging.io.Load - Identified/registered ds:itemId {2da45ade-e2fe-4251-9c73-a623aa57ebb0}
[main] INFO org.docx4j.openpackaging.io3.Load3 - package read;  elapsed time: 10932 ms
[main] INFO org.docx4j.openpackaging.parts.JaxbXmlPart - Lazily unmarshalling /word/document.xml
[main] INFO org.docx4j.openpackaging.parts.JaxbXmlPartXPathAware - For org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart, unmarshall via binder
[main] INFO org.docx4j.openpackaging.contenttype.ContentTypeManager - marshalling org.docx4j.openpackaging.contenttype.ContentTypeManager ...
[main] INFO org.docx4j.jaxb.NamespacePrefixMapperUtils - Using NamespacePrefixMapperSunInternal, which is suitable for Java 6
[main] INFO org.docx4j.openpackaging.parts.JaxbXmlPart - marshalling org.docx4j.openpackaging.parts.relationships.RelationshipsPart
[main] INFO org.docx4j.openpackaging.parts.JaxbXmlPart - marshalling org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart
[main] INFO org.docx4j.openpackaging.parts.JaxbXmlPart - marshalling org.docx4j.openpackaging.parts.relationships.RelationshipsPart
[main] INFO org.docx4j.openpackaging.parts.JaxbXmlPart - marshalling org.docx4j.openpackaging.parts.WordprocessingML.BibliographyPart
[main] INFO org.docx4j.openpackaging.parts.JaxbXmlPart - marshalling org.docx4j.openpackaging.parts.relationships.RelationshipsPart
[main] INFO org.docx4j.openpackaging.parts.JaxbXmlPart - marshalling org.docx4j.openpackaging.parts.CustomXmlDataStoragePropertiesPart
[main] INFO org.docx4j.openpackaging.io3.Save - ...Done!
Operation Completed

Однако в Yohan2.docx ничего не изменилось, это чистая копия Yohan.docx. Что я здесь сделал не так?

ОБНОВЛЕНИЕ

Я протестировал пример MERGEFIELD из GITHUB, но он тоже не сработал. Ниже вывод, напечатанный в консоли

[main] INFO org.docx4j.jaxb.Context - java.vendor=Oracle Corporation
[main] INFO org.docx4j.jaxb.Context - java.version=1.8.0_05
[main] INFO org.docx4j.jaxb.Context - No MOXy JAXB config found; assume not intended..
[main] INFO org.docx4j.jaxb.NamespacePrefixMapperUtils - Using NamespacePrefixMapperSunInternal, which is suitable for Java 6
[main] INFO org.docx4j.jaxb.Context - Using Java 6/7 JAXB implementation
[main] INFO org.docx4j.jaxb.Context - Not using MOXy; using com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl
[main] WARN org.docx4j.utils.ResourceUtils - Couldn't get resource: docx4j.properties
[main] WARN org.docx4j.Docx4jProperties - Couldn't find/read docx4j.properties; docx4j.properties not found via classloader.
[main] INFO org.docx4j.XmlUtils - Using com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl
[main] INFO org.docx4j.XmlUtils - Using com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl
[main] INFO org.docx4j.openpackaging.contenttype.ContentTypeManager - Detected WordProcessingML package 
[main] INFO org.docx4j.openpackaging.io3.Load3 - Instantiated package of type org.docx4j.openpackaging.packages.WordprocessingMLPackage
[main] INFO org.docx4j.utils.XPathFactoryUtil - xpath implementation: org.apache.xpath.jaxp.XPathFactoryImpl
[main] WARN org.docx4j.openpackaging.contenttype.ContentTypeManager - DefaultPart used for part '/word/stylesWithEffects.xml' of content type 'application/vnd.ms-word.stylesWithEffects+xml'
[main] INFO org.docx4j.openpackaging.io3.Load3 - package read;  elapsed time: 14766 ms
[main] INFO org.docx4j.openpackaging.parts.JaxbXmlPart - Lazily unmarshalling /word/document.xml
[main] INFO org.docx4j.openpackaging.parts.JaxbXmlPartXPathAware - For org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart, unmarshall via binder
[main] INFO org.docx4j.model.fields.merge.MailMerger - Found 9 fields 
[main] INFO org.docx4j.model.fields.merge.MailMerger - Key: 'kundenname'
[main] INFO org.docx4j.model.fields.merge.MailMerger - Key: 'kundenname'
[main] INFO org.docx4j.model.fields.merge.MailMerger - Key: 'kundenname'
[main] INFO org.docx4j.model.fields.merge.MailMerger - Key: 'Kundenname'
[main] INFO org.docx4j.model.fields.merge.MailMerger - Key: 'KunDenName'
[main] INFO org.docx4j.model.fields.merge.MailMerger - Key: 'KUNDENNAME'
[main] INFO org.docx4j.model.fields.merge.MailMerger - Key: 'Kundenstrasse'
[main] INFO org.docx4j.model.fields.merge.MailMerger - Key: 'yourdate'
[main] INFO org.docx4j.model.fields.DateFormatInferencer - Infering dates based using International formats
[main] INFO org.docx4j.model.fields.merge.MailMerger - Key: 'yournumber'
[main] INFO org.docx4j.openpackaging.parts.JaxbXmlPart - Lazily unmarshalling /word/settings.xml
[main] INFO org.docx4j.openpackaging.parts.JaxbXmlPartXPathAware - For org.docx4j.openpackaging.parts.WordprocessingML.DocumentSettingsPart, unmarshall via binder
[main] INFO org.docx4j.openpackaging.contenttype.ContentTypeManager - marshalling org.docx4j.openpackaging.contenttype.ContentTypeManager ...
[main] INFO org.docx4j.jaxb.NamespacePrefixMapperUtils - Using NamespacePrefixMapperSunInternal, which is suitable for Java 6
[main] INFO org.docx4j.openpackaging.parts.JaxbXmlPart - marshalling org.docx4j.openpackaging.parts.relationships.RelationshipsPart
[main] INFO org.docx4j.openpackaging.parts.JaxbXmlPart - marshalling org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart
[main] INFO org.docx4j.openpackaging.parts.JaxbXmlPart - marshalling org.docx4j.openpackaging.parts.relationships.RelationshipsPart
[main] INFO org.docx4j.openpackaging.parts.JaxbXmlPart - marshalling org.docx4j.openpackaging.parts.WordprocessingML.DocumentSettingsPart
[main] WARN org.docx4j.openpackaging.parts.WordprocessingML.DocumentSettingsPart - 
[main] INFO org.docx4j.openpackaging.io3.Save - ...Done!
[main] INFO org.docx4j.model.fields.merge.MailMerger - Found 9 fields 
[main] INFO org.docx4j.model.fields.merge.MailMerger - Key: 'kundenname'
[main] INFO org.docx4j.model.fields.merge.MailMerger - Key: 'kundenname'
[main] INFO org.docx4j.model.fields.merge.MailMerger - Key: 'kundenname'
[main] INFO org.docx4j.model.fields.merge.MailMerger - Key: 'Kundenname'
[main] INFO org.docx4j.model.fields.merge.MailMerger - Key: 'KunDenName'
[main] INFO org.docx4j.model.fields.merge.MailMerger - Key: 'KUNDENNAME'
[main] INFO org.docx4j.model.fields.merge.MailMerger - Key: 'Kundenstrasse'
[main] INFO org.docx4j.model.fields.merge.MailMerger - Key: 'yourdate'
[main] INFO org.docx4j.model.fields.merge.MailMerger - Key: 'yournumber'
[main] INFO org.docx4j.openpackaging.contenttype.ContentTypeManager - marshalling org.docx4j.openpackaging.contenttype.ContentTypeManager ...
[main] INFO org.docx4j.openpackaging.parts.JaxbXmlPart - marshalling org.docx4j.openpackaging.parts.relationships.RelationshipsPart
[main] INFO org.docx4j.openpackaging.parts.JaxbXmlPart - marshalling org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart
[main] INFO org.docx4j.openpackaging.parts.JaxbXmlPart - marshalling org.docx4j.openpackaging.parts.relationships.RelationshipsPart
[main] INFO org.docx4j.openpackaging.parts.JaxbXmlPart - marshalling org.docx4j.openpackaging.parts.WordprocessingML.DocumentSettingsPart
[main] WARN org.docx4j.openpackaging.parts.WordprocessingML.DocumentSettingsPart - 
[main] INFO org.docx4j.openpackaging.io3.Save - ...Done!

person JustCause    schedule 22.09.2014    source источник


Ответы (2)


Заполнитель, вставленный через Ссылка > Вставить ссылку > Добавить новый заполнитель, приводит к чему-то вроде:

  <w:sdt>
    <w:sdtPr>
      <w:id w:val="-963732549"/>
      <w:citation/>
    </w:sdtPr>
    <w:sdtContent>
      <w:r>
        <w:fldChar w:fldCharType="begin"/>
      </w:r>
      <w:r>
        <w:rPr>
          <w:lang w:val="en-AU"/>
        </w:rPr>
        <w:instrText xml:space="preserve"> CITATION PL1 \l 3081 </w:instrText>
      </w:r>
      <w:r>
        <w:fldChar w:fldCharType="separate"/>
      </w:r>
      <w:r>
        <w:rPr>
          <w:noProof/>
          <w:lang w:val="en-AU"/>
        </w:rPr>
        <w:t>(PL1)</w:t>
      </w:r>
      <w:r>
        <w:fldChar w:fldCharType="end"/>
      </w:r>
    </w:sdtContent>
  </w:sdt>

т.е. поле CITATION, обернутое в элементе управления содержимым.

docx4j имеет API для замены полей MERGEFIELD и DOCPROPERTY, но не полей CITATION.

Есть ли особая причина, по которой вы пытаетесь использовать поле CITATION?

Если вы можете переключиться на поле MERGEFIELD или DOCPROPERTY, я бы сделал это. В противном случае вы можете изучить код docx4j для их обработки и адаптировать его для обработки CITATION.

person JasonPlutext    schedule 22.09.2014
comment
У меня нет причин использовать поле цитирования. Я нашел это как способ создания заполнителей в одном из видео. Как создать Docx4j совместимый заполнитель? - person JustCause; 23.09.2014
comment
Insert › Quick Parts › Field, хотя лично я предпочитаю использовать привязку данных управления контентом. - person JasonPlutext; 23.09.2014
comment
Может быть, слишком много, чтобы спросить, но как я могу связаться с вами лично, чтобы решить мои проблемы с библиотекой? - person JustCause; 23.09.2014
comment
Привет, я не вижу Place Holder в Insert > Quick Parts > Field ? Какой из них я должен выбрать? - person JustCause; 23.09.2014
comment
Я добавил MergeField, но с приведенным выше кодом все равно не получилось :( - person JustCause; 23.09.2014
comment
См. github.com/plutext /docx4j/blob/master/src/samples/docx4j/org/ - person JasonPlutext; 23.09.2014
comment
Привет, попробовал твой пример. Это тоже не сработало. Разве это не работает в Java 8? - person JustCause; 24.09.2014
comment
Должно работать в Java 8. Создайте еще один вопрос и поместите входной документ где-нибудь в Интернете для проверки. - person JasonPlutext; 24.09.2014

Заполнитель в «Вставка» > «Быстрые детали» > «Поле»

Выберите поле слияния

Скопируйте имя поля слияния, которое отображается в документе, вместе со стрелками в свой код. replacePlaceholder(шаблон,"Самолет","имя-заполнитель со стрелками");

person ozogla    schedule 06.11.2014