Page 1 of 1

How to generate the custom Xml part in Java?

PostPosted: Wed Feb 23, 2011 1:07 am
by cuchillo155
Hi there,

I am new in docx4j Java library.
I need it because I have to make text substitutions in Word templates using content controls.
The sample CustomXmlBinding.java is very useful to do this job!
Now I explain you my issue.

I created a docx Word template, adding some content controls.
After that I used Word 2007 Content Control Toolkit tool to bind the controls ( as explained here http://cultivatingcode.com/2010/10/13/generating-word-documents-p2/ ).
Unzipping the original and the new word documents in two folders, and using WinMerge tool to compare them, I saw these changes:

- the file [Content_Types].xml has a new <Ovveride> tag
( in my case: <Override PartName="/customXml/itemProps1.xml" ContentType="application/vnd.openxmlformats-officedocument.customXmlProperties+xml" /> )

- the file /word/_rels/document.xml.rels has a new Relationship
( in my case: <Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml" Target="../customXml/item1.xml" Id="Rdb0b6908904d430a" /> )

- There is a new directory customXml that contains these files:
- item1.xml that states the content controls
- itemProps1.xml that contains the itemID
- _rels/item1.xml.rels that has 1 relationship to the file /customXml/itemProps1.xml

- the file /word/document.xml added a new <w:dataBinding> tag inside every <w:sdt> tag ( the <w:dataBinding> tag has 2 attributes: w:xpath and w:storeItemID )


I was wondering which is the quickest way to make these steps in Java. Looking into the docx4j source code, I think I have to work with these classes:
- org.docx4j.openpackaging.parts.CustomXmlDataStoragePart.java
- org.docx4j.openpackaging.parts.CustomXmlDataStoragePropertiesPart.java
- org.docx4j.model.datastorage.OpenDoPEHandler.java

The sample CreateDocxWithCustomXml.java is useful, but not enough in my case.

Any help please?


Thanks
Kind Regards
Stefano

Re: How to generate the custom Xml part in Java?

PostPosted: Wed Feb 23, 2011 11:34 pm
by jason
Please see the example http://dev.plutext.org/trac/docx4j/brow ... omXml.java which I just fleshed out a little bit for you.

I didn't test it, but hopefully it works for you without any significant alteration.

Regarding adding a new <w:dataBinding> tag inside every <w:sdt> tag, the relevant element is CTDataBinding.

You'd do something like sdtPr.setDataBinding(dataBinding);

And you can do dataBinding.setStoreItemID(newItemId) etc.

Re: How to generate the custom Xml part in Java?

PostPosted: Sat Apr 16, 2011 3:45 am
by adi
Hi Jason

I would like to add a CTDataBinding to stdPr with sdtPr.setDataBinding(dataBinding) and then save the document.

here my code:
org.docx4j.wml.ObjectFactory factory = new org.docx4j.wml.ObjectFactory();
org.docx4j.wml.CTDataBinding dataBinding = factory.createCTDataBinding();
dataBinding.setStoreItemID(dataBindingStoreItemId);
dataBinding.setXpath(xpath);
//dataBinding.setParent(sdtPr);
dataBinding.setPrefixMappings(prefixMappings);

sdtPr.setDataBinding(dataBinding);

// save it
wordMLPackage.save(new java.io.File(saveFile));

by saving i receive the exception:

Caused by: javax.xml.bind.MarshalException
- with linked exception:
[com.sun.istack.internal.SAXException2: unable to marshal type "org.docx4j.wml.CTDataBinding" as an element because it is missing an @XmlRootElement annotation]
at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:303)
at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:229)
at javax.xml.bind.helpers.AbstractMarshallerImpl.marshal(AbstractMarshallerImpl.java:107)
at org.docx4j.XmlUtils.marshaltoString(XmlUtils.java:417)
... 3 more
Caused by: com.sun.istack.internal.SAXException2: unable to marshal type "org.docx4j.wml.CTDataBinding" as an element because it is missing an @XmlRootElement annotation
at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.reportError(XMLSerializer.java:225)
at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeRoot(ClassBeanInfoImpl.java:269)
at com.sun.xml.internal.bind.v2.runtime.property.ArrayReferenceNodeProperty.serializeListBody(ArrayReferenceNodeProperty.java:90)
at com.sun.xml.internal.bind.v2.runtime.property.ArrayERProperty.serializeBody(ArrayERProperty.java:128)
at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:288)
at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:675)
at com.sun.xml.internal.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:107)
at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:288)
at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsSoleContent(XMLSerializer.java:570)
at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeRoot(ClassBeanInfoImpl.java:278)
at com.sun.xml.internal.bind.v2.runtime.property.ArrayReferenceNodeProperty.serializeListBody(ArrayReferenceNodeProperty.java:90)


could you please add @XmlRootElement annotation to CTDataBinding or do you know any other way to get rid off this exception?

Thank you
Adrian

Re: How to generate the custom Xml part in Java?

PostPosted: Sat Apr 16, 2011 12:10 pm
by jason
Hello Adrian

http://dev.plutext.org/trac/docx4j/changeset/1469 adds this.

I'll produce a "nightly" build later today.

cheers .. Jason

Re: How to generate the custom Xml part in Java?

PostPosted: Mon Apr 18, 2011 7:51 pm
by adi
Hi Jason

wow, you were so fast...

Thank you very much, it works now.
Adrian

Re: How to generate the custom Xml part in Java?

PostPosted: Thu Apr 21, 2011 1:29 am
by jason
No worries - I try to respond quickly, since I realize there are better things than waiting for responses which may or may not come :-)

Re: How to generate the custom Xml part in Java?

PostPosted: Sat Feb 18, 2012 1:24 am
by urobe
Hi, I have a question which I believe is related to this thread. I'm also interested in creating the custom XML part in Java. I've created a template, with a custom control, a snippet of my template is

Code: Select all
<w:sdt>
<w:sdtPr>
  <w:rPr>...</w:rPr>
  <w:alias w:val="customer's name"/>
  <w:tag w:val="customer.name"/>
  <w:id w:val="61461838"/>
  <w:placeholder>
    <w:docPart w:val="DefaultPlaceholder_22675703"/>
  </w:placeholder>
<w:text/>
</w:sdtPr>
<w:sdtContent>
...
</w:sdtContent>
</w:sdt>


What I now would need is that the data binding is set as follows

Code: Select all
<w:sdt>
<w:sdtPr>
  <w:rPr>...</w:rPr>
  <w:alias w:val="customer's name"/>
  <w:tag w:val="customer.name&od:xpath=customername"/>
  <w:id w:val="61461838"/>
  <w:placeholder>
  <w:docPart w:val="DefaultPlaceholder_22675703"/>
  </w:placeholder>
  <w:dataBinding w:xpath="/customer/name" w:storeItemID="{6B8BD713-1E67-4702-B334-757ECDFC6CE2}"/>
<w:text/>
</w:sdtPr>
<w:sdtContent>
...
</w:sdtContent>
</w:sdt>


The snipped above was created using the Word Add in to achieve the binding. However, I'd like to avoid this and let the author of the template specify the binding in the tag instead. A preprossing step should patch the binding, by finding the std tag, reading & parsing the tag and creating the binding. Afterwards, I assume, the bindings can be applied using the standard mechanisms like
Code: Select all
BindingHandler.applyBindings(wordMLPackage.getMainDocumentPart());


From the thread her I have learned to create a binding using CTDataBinding, however how to I find my std tags, how do I read the tag content?
Any help to achieve this would be highly appreciated!
Thanks in advance
Chris

Re: How to generate the custom Xml part in Java?

PostPosted: Sat Feb 18, 2012 10:43 am
by jason
urobe wrote:how to I find my std tags, how do I read the tag content?


You can find your tags using TraversalUtils (which is what OpenDoPEHandler does), or via XPath - both of these approaches are described in the Getting Started document.

If you have a look at the OpenDopeHandler code, you'll see an example of reading tag content.

Code: Select all
Tag tag = getSdtPr(sdt).getTag();