Page 1 of 1

Add w:sdt content control programmatically

PostPosted: Mon Oct 15, 2012 10:39 pm
by davidtor
I'm new to the docx4j world and this is my first post! :-D
I'm building a small java program to test all the "document related" features i need to cover to fulfill my project requirements. That is, being able to create templates with "content controls" that will offer as raw template to the users. Let the user enhance them, to finally populate them with data. I'm dealing with "docx4j" because of the "repeating and conditional" features.

This has been my progress:

I want to, programmatically:
1) Create a blank document (DONE)
2) Add a custom xml part with the xml data (the part3.xml in the invoice example). (DONE)
3) Add a custom xml part with the xml xpaths reference (the part4.xml in the invoice example). (DONE)
4) Add the content control <w:sdt> (PENDING)
Something similar to this extract from the invoice example:
Code: Select all

    <w:alias w:val="Customer name" />
    <w:tag w:val="od:xpath=x1&customer name=customer name" />
    <w:id w:val="1418037941" />
      <w:docPart w:val="DefaultPlaceholder_22675703" />
    <w:dataBinding w:xpath="/invoice[1]/customer[1]/name[1]" w:storeItemID="{8B049945-9DFE-4726-9DE9-CF5691E53858}" />
    <w:text />
        <w:t>Joe Bloggs</w:t>

And here is my question: How to generate this xml ? Can be done by Java code or only from Word? What are and how are generated the "1418037941" and the "DefaultPlaceholder_22675703" values? I guess i cannot "invent" them, and are referenced somewhere else.
I was looking for some method in MainDocumentPart class to do so but was unable to find it.
Am i misunderstandig something?

The other steps are almost ok:

5) Perform "preprocess" (DONE)
6) Perform "process" (DONE)
7) Perform "strip" (DONE, except removing repat tags)

Thank you very much for your help!

Re: Add w:sdt content control programmatically

PostPosted: Tue Oct 16, 2012 5:49 pm
by jason

Re: Add w:sdt content control programmatically

PostPosted: Tue Oct 16, 2012 7:02 pm
by davidtor
Ok, i have seen that. Thanks!

Re: Add w:sdt content control programmatically

PostPosted: Thu Mar 20, 2014 7:55 pm
by willi.firulais

This is an old tread, but the problem reported seems to remain
(as David reported

I have found one strange thing. When <w:sdt> is generated, the nested <w:sdtPr>...</w:sdtPr> tag is ok, but the nested tag <w:sdtContent><w:p><w:r><w:t>Joe Bloggs</w:t></w:r></w:p></w:sdtContent> appears empty, like <w:sdtContent/>. When i open the docx in Word, the content control is there, but lacks the "default text" Joe Bloggs.

I've tried adding a checkbox using

Code: Select all
sdtElement = (SdtBlock) XmlUtils.unmarshalString(xml, Context.jc, SdtBlock.class );

but the sdtContent dissapears after after the unmarshal.

If giving a w:p around the whole XML the unmarschall works fine.

Has someone some hints or Workaround on this?

regards, Willi

Code: Select all
    protected void addCheckbox(BlockBox blockBox) {
        String xml =
        "<w:sdt xmlns:w=\"\" xmlns:w14=\"\">\n" +
        "  <w:sdtPr>\n" +
        "    <w14:checkbox>\n" +
        "      <w14:checked w14:val=\""+"1"+"\"/>\n" +
        "      <w14:checkedState w14:val=\"2612\" w14:font=\"MS Gothic\"/>\n" +
        "      <w14:uncheckedState w14:val=\"2610\" w14:font=\"MS Gothic\"/>\n" +
        "    </w14:checkbox>\n" +
        "  </w:sdtPr>\n" +
        "  <w:sdtContent>\n" +
        "    <w:r>\n" +
        "      <w:rPr>\n" +
        "        <w:rFonts w:ascii=\"MS Gothic\" w:eastAsia=\"MS Gothic\" w:hAnsi=\"MS Gothic\" w:hint=\"eastAsia\"/>\n" +
        "      </w:rPr>\n" +
        "      <w:t>" +"☐"+ "</w:t>\n" +
        "    </w:r>\n" +
        "  </w:sdtContent>\n" +

        org.docx4j.wml.SdtBlock sdtElement = (SdtBlock) XmlUtils.unmarshalString(xml, Context.jc, SdtBlock.class );

        System.out.println(XmlUtils.marshaltoString(sdtElement, true, true) );


Re: Add w:sdt content control programmatically

PostPosted: Thu Mar 20, 2014 8:14 pm
by willi.firulais

Have found that this Workaround is doing the Job.
Seems that this way the w:sdtContent doen't get killed by the Marshaller.

Code: Select all
  org.docx4j.wml.P p = null;
  p = (org.docx4j.wml.P) XmlUtils.unmarshalString(xml);