Page 1 of 1

Replace tablecell with HTML content

PostPosted: Wed Jan 30, 2013 6:30 am
by kvmc09302012
How to replace a place holder inside a table cell with HTML content in docx.

I have a docx template and it has some place holder. It also has a table in it with a header row and the next row has place holder strings. I was successful in replacing the text and also add rows inside the table. Now I need to replace a placeholder inside a table cell with html content. However, I could only replace with HTML content outside the table, but not inside the table cell. Please help.

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
package samplepackage;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import org.docx4j.jaxb.Context;
import org.docx4j.openpackaging.contenttype.ContentType;
import org.docx4j.openpackaging.exceptions.Docx4JException;
import org.docx4j.openpackaging.exceptions.InvalidFormatException;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.PartName;
import org.docx4j.openpackaging.parts.WordprocessingML.AlternativeFormatInputPart;
import org.docx4j.relationships.Relationship;
import org.docx4j.wml.CTAltChunk;
import org.docx4j.wml.Text;


public class SecondSample {

    static WordprocessingMLPackage pack = null;
    final static String XPATH_TO_SELECT_TEXT_NODES = "//w:t";
    final static String xhtml = "<html><head><title>Import me</title></head><body><p>Hello World!</p></body></html>";
    Properties templateProperties = new Properties();

    public static void main(String args[]) throws Docx4JException, FileNotFoundException, JAXBException, IOException {
        SecondSample ss = new SecondSample();
        pack = ss.getTemplate("doctemplates\\template2.docx");
        ss.replacePlaceholders();
        ss.writeDocxToStream(pack, "doctemplates\\result" + System.currentTimeMillis() + ".docx");
    }

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

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

    private void replacePlaceholders() throws JAXBException {

        int index;

        try {
           
            loadProp();
        } catch (Exception e) {
            e.printStackTrace();
        }

        List<Object> texts = pack.getMainDocumentPart()
                .getJAXBNodesViaXPath(XPATH_TO_SELECT_TEXT_NODES, true);

        for (Object obj : texts) {
            Text text = (Text) ((JAXBElement) obj).getValue();

            if (isHTMLPlaceholder(text.getValue())) {
                //replace element with HTML content    
                System.out.println("New HTML Placeholder found");
                index = texts.indexOf(obj);
                replaceHTML(index, text.getValue(), templateProperties);

                //remove superflous placeholder
                pack.getMainDocumentPart().getContent().remove(index);

            } else {

                //replace Node with normal text
                if (templateProperties.containsKey(text.getValue())) {
                    System.out.println("New TEXT Placeholder found");
                    String textValue = replacePlaceholdersByValue(text.getValue(), templateProperties);
                    text.setValue(textValue);
                }
            }

        }
    }

    private boolean isHTMLPlaceholder(String placeholderValue) {
        if (placeholderValue.equalsIgnoreCase("[id_html]")) {
            return true;
        }
        return false;
    }

    //Replace Placeholders with HTML
    private void replaceHTML(int index, String placeholderValue, Properties templateProperties) {

        String methodName = "";

        try {
            if (templateProperties.containsKey(placeholderValue)) {
                methodName = (String) templateProperties.get(placeholderValue);
                System.out.println("Placeholder gefunden: " + methodName);
                placeholderValue = methodName;
            }

        } catch (Exception e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        }

        String html = placeholderValue;
        AlternativeFormatInputPart afiPart = null;

        //Create HTML
        try {
            System.out.println("Trying to create an html part.");
            afiPart = new AlternativeFormatInputPart(new PartName("/hw" + String.valueOf(index) + ".html")); //CAUTION: each html part needs a new name!!
        } catch (InvalidFormatException e) {
            e.printStackTrace();
        }

        //Parse Content
        System.out.println("Get the Bytes and set the Content type of the html part.");
        afiPart.setBinaryData(html.getBytes());
        afiPart.setContentType(new ContentType("text/html"));

        Relationship altChunkRel = null;

        try {
            System.out.println("adding the Target Path...");
            altChunkRel = pack.getMainDocumentPart().addTargetPart(afiPart);
        } catch (InvalidFormatException e) {
            e.printStackTrace();
        }

        //Add HTML to document
        System.out.println("Adding HTML to the document..");
        CTAltChunk ac = Context.getWmlObjectFactory().createCTAltChunk();
        ac.setId(altChunkRel.getId());
        pack.getMainDocumentPart().getContent().add(index - 1, ac);
    }

    //Replace Placeholders with text
    private String replacePlaceholdersByValue(String placeholderValue, Properties templateProperties) {
        String methodName = "";
        try {
            if (templateProperties.containsKey(placeholderValue)) {
                methodName = (String) templateProperties.get(placeholderValue);
                System.out.println("Placeholder gefunden: " + methodName);
                placeholderValue = methodName;
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        }

        return placeholderValue;
    }

    private void loadProp() {
        try {
            ClassLoader loader = SecondSample.class.getClassLoader();
            if (loader == null) {
                loader = ClassLoader.getSystemClassLoader();
            }
            String propFile = "template.properties";
            InputStream inputStream = loader.getResourceAsStream(propFile);
            templateProperties = new Properties();
            templateProperties.load(inputStream);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 
Parsed in 0.028 seconds, using GeSHi 1.0.8.4

template.properties

    [ID_TITLE]=Sample Letter
    [ID_NAME]=Sam
    [ID_DESC]=description
    [ID_VALUE]=100
    [ID_VALUE2]=200
    [ID_HTML]=<html><body><b>Hello World!</b></body></html>

Re: Replace tablecell with HTML content

PostPosted: Wed Jan 30, 2013 8:13 pm
by jason
What goes wrong? Does your code find the w:t in the table cell? Does it insert your AFIP?

Re: Replace tablecell with HTML content

PostPosted: Fri Feb 01, 2013 4:43 am
by kvmc09302012
It does find the placeholder, but instead of replacing the place holder with html content inside the table cell, it replaces them at the end of the document. I also tried doing this
Code: Select all
pack.getMainDocumentPart().getJaxbElement().getContent().remove(index);

instead of
Code: Select all
pack.getMainDocumentPart().getContent().add(index-1,ac);


but no luck. To summaries, the problem i am facing is ,
1) unable to replace the place holder with html content inside a table cell . The replaced content appears outside the table and usually at the end of the document.
2) the place holder for HTML content appears in the cell as is. It is not being removed.

thanks.

Re: Replace tablecell with HTML content

PostPosted: Fri Feb 01, 2013 6:02 pm
by jason
You need to review your approach.

You are replacing at some index in the block level content, where that index is an index into your list of found items. This is wrong, whether tables are involved or not.

If you unzip a docx and look at document.xml, you'll see that a table can be a block level item. It is made up of rows and cells, similar to HTML tables. Each table cell has its own content list; you need to manipulate that.

My recommendation is to drop the XPath approach entirely, and either use traversal or content control data binding. See Getting Started for more info.

Re: Replace tablecell with HTML content

PostPosted: Sat Feb 09, 2013 11:41 am
by kvmc09302012
Thanks for your reply. Can you please provide me some source code to start with.