Docx4J并没有取代占位符

时间:2014-09-22 13:20:25

标签: java io docx docx4j

我正在尝试更换一个简单的“地方持有人in MS Word 2007 using Docx4J . I created the placeholder by参考>插入引文>添加新占位符`

以下是我的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的纯文本。我在这做错了什么?

更新

我测试了GITHUB的MERGEFIELD示例,但它也没有用。以下是在控制台中打印的输出

[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!

2 个答案:

答案 0 :(得分:1)

通过参考&gt;插入的占位符插入引文&gt;添加新的占位符结果如下:

  <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有一个用于替换MERGEFIELD和DOCPROPERTY字段的API,但不包含CITATION字段。

您是否有特殊原因试图使用CITATION字段?

如果你可以换成MERGEFIELD或DOCPROPERTY字段,我会这样做。否则,您可以检查docx4j的代码以处理它们,并使其适应处理CITATION。

答案 1 :(得分:0)

将插页放在插页中&gt;快速部件&gt;字段

选择MergeField

将文档中显示的合并字段名称与箭头字符一起复制到代码中。 replacePlaceholder(模板, “平面”, “placeholdernamewitharrowcharacters”);