Page 1 of 1

Tip - constructing complex objects

PostPosted: Mon Aug 11, 2008 5:48 am
by jason
Suppose you want to add a horizontal line to your document (the equivalent of HTML's <hr/>).

The following code would work:

Code: Select all
               org.docx4j.wml.P p = wordMLPackage.getMainDocumentPart()
                     .addParagraphOfText(null);
               org.docx4j.wml.PPr pPr = factory.createPPr();
               p.setPPr(pPr);
               org.docx4j.wml.PPrBase.PBdr bdr = factory
                     .createPPrBasePBdr();
               org.docx4j.wml.CTBorder bottom = factory.createCTBorder();
               pPr.setPBdr(bdr);
               bdr.setBottom(bottom);
               bottom.setVal(org.docx4j.wml.STBorder.SINGLE);
               bottom.setSz(new java.math.BigInteger("6"));
               bottom.setSpace(new java.math.BigInteger("1"));
               bottom.setColor("auto");
               wordMLPackage.getMainDocumentPart()
                     .addParagraphOfText(null);


But that is very painful to write; and you are only likely to get it right if you are looking at the OpenXML that Word produces after you have made a horizontal line in Word. For example:
Code: Select all
        <w:p>
            <w:pPr>
                <w:pBdr>
                    <w:bottom w:val="single" w:sz="6" w:space="1" w:color="auto" />
                </w:pBdr>
            </w:pPr>
        </w:p>


It'd be nice to be able to give JAXB the snippet of XML which represents the horizontal line, and say "now generate the equivalent Java for me". But JAXB doesn't provide that out of the box - see this post.

Another way to avoid writing that tedious code is to start with a snippet of XML as a string, and then unmarshall it. You can use org.docx4j.XmlUtils.unmarshalString to do this.

docx4j svn changeset 526 provides a further method, which substitutes substrings of the form ${key1} with the values to which they are mapped. For example, to add a table with different values:

Code: Select all
    // Contains ${version}, ${modifier}, ${date}, ${message}
    final String versionHistoryTableTemplate = "<w:tbl xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\">
<w:tblPr><w:tblStyle w:val=\"TableGrid\"/><w:tblW w:w=\"0\" w:type=\"auto\"/><w:tblLook w:val=\"04A0\"/></w:tblPr>
<w:tblGrid><w:gridCol w:w=\"3192\"/><w:gridCol w:w=\"3192\"/><w:gridCol w:w=\"3192\"/></w:tblGrid>
<w:tr><w:tc><w:tcPr><w:tcW w:w=\"3192\" w:type=\"dxa\"/></w:tcPr><w:p><w:r><w:t>${version}</w:t></w:r></w:p></w:tc><w:tc><w:tcPr><w:tcW w:w=\"3192\" w:type=\"dxa\"/></w:tcPr><w:p><w:r><w:t>${modifier}</w:t></w:r></w:p></w:tc><w:tc><w:tcPr><w:tcW w:w=\"3192\" w:type=\"dxa\"/></w:tcPr><w:p><w:r><w:t>${date}</w:t></w:r></w:p></w:tc></w:tr>
<w:tr><w:tc><w:tcPr><w:tcW w:w=\"9576\" w:type=\"dxa\"/><w:gridSpan w:val=\"3\"/></w:tcPr><w:p><w:r><w:t>${message}</w:t></w:r></w:p></w:tc></w:tr></w:tbl>";

            java.util.HashMap<String, String>mappings = new java.util.HashMap<String, String>();
            mappings.put("version", "some value");
            mappings.put("modifier", "some value");
            mappings.put("date", "some value");
            mappings.put("method", "some value");

            wordMLPackage.getMainDocumentPart().addObject(
                  org.docx4j.XmlUtils.unmarshallFromTemplate(versionHistoryTableTemplate, mappings ) );


Thanks to this post for the inspiration.