{"id":462,"date":"2018-04-28T20:28:55","date_gmt":"2018-04-28T10:28:55","guid":{"rendered":"https:\/\/www.docx4java.org\/blog\/?p=462"},"modified":"2018-04-29T09:25:41","modified_gmt":"2018-04-28T23:25:41","slug":"from-variablereplace-to-opendope-data-binding","status":"publish","type":"post","link":"https:\/\/www.docx4java.org\/blog\/2018\/04\/from-variablereplace-to-opendope-data-binding\/","title":{"rendered":"From VariableReplace to OpenDoPE data binding"},"content":{"rendered":"<p>This blog post is a walkthrough of how to easily move from variable replacement to OpenDoPE content control data binding.<\/p>\n<p><strong>Introduction<\/strong><\/p>\n<p><a href=\"https:\/\/github.com\/plutext\/docx4j\/blob\/master\/src\/samples\/docx4j\/org\/docx4j\/samples\/VariableReplace.java\">Variable replacement<\/a> is quite a popular way to get started generating Word documents.<\/p>\n<p>I guess that&#8217;s because developers expect this sort of approach to be available, and its <em>easy<\/em>: all you have to do is add your variables to the document, then bang, you replace them.<\/p>\n<p>But its not all a bed of roses, there&#8217;s some thorns in there too:<\/p>\n<ol>\n<li>the so-called &#8220;split run&#8221; problem, in which Word has split your variable name across more than one XML element, due to formatting, spelling\/grammar etc<\/li>\n<li>variable replacement is great if you just want to replace text, but what if you want to replace images, conditionally include\/exclude content, or repeat table rows or list entries?<\/li>\n<\/ol>\n<p>Content control data binding is a great solution to these problems.<\/p>\n<p>Your data (provided in XML format) is bound to content controls using XPath, and with the OpenDoPE conventions, this approach offers:<\/p>\n<ul>\n<li>conditional inclusion\/exclusion<\/li>\n<li>repeats (<a href=\"\/blog\/2015\/01\/word-2013-repeatingsection-content-controls-ready-for-prime-time\/\">Word 2013 has its own repeating content controls<\/a>)<\/li>\n<li>nesting of repeats and conditionals<\/li>\n<li>add picture\/image<\/li>\n<li>import escaped XHTML<\/li>\n<\/ul>\n<p>Some users create very complex\u00a0contracts and reports this way.<\/p>\n<p><strong>Automated Migration<\/strong><\/p>\n<p>The good news is that docx4j contains code to automatically migrate\u00a0a document\u00a0which has\u00a0variables on its surface, to one which contains OpenDoPE content controls.<\/p>\n<p>The code is in <a href=\"https:\/\/github.com\/plutext\/docx4j\/blob\/master\/src\/main\/java\/org\/docx4j\/model\/datastorage\/migration\/FromVariableReplacement.java\">FromVariableReplacement.java<\/a><\/p>\n<p>Have a <a href=\"https:\/\/github.com\/plutext\/docx4j\/blob\/master\/src\/main\/java\/org\/docx4j\/model\/datastorage\/migration\/FromVariableReplacement.java#L201\">look at the main method<\/a> to see how to use it.<\/p>\n<p>There have been some fixes recently, so you should use <a href=\"https:\/\/www.docx4java.org\/docx4j\/docx4j-nightly-20180428.jar\">docx4j-nightly-20180428.jar<\/a> (or 3.3.8 when released) or later.<\/p>\n<p>OK, let&#8217;s assume you now have a docx file with content controls in it.\u00a0 You may want to further develop your template.\u00a0 For this you need an OpenDoPE Authoring tool.<\/p>\n<p><strong>OpenDoPE Authoring<\/strong><\/p>\n<p>The\u00a0friendliest\u00a0OpenDoPE authoring tool is the <a href=\"https:\/\/github.com\/plutext\/OpenDoPE-NoXML-WordAddIn\">&#8220;No-XML&#8221; Word AddIn<\/a>.<\/p>\n<p>With this it is very easy to add conditions, but\u00a0the limitation is that it assumes a fixed XML format.\u00a0 \u00a0If you want to use your own XML format (or to bind escaped XHTML I suspect), you&#8217;ll need to use one of the older add ins.<\/p>\n<p>Here we&#8217;ll walk through adding a condition with &#8220;No XML&#8221; add in.<\/p>\n<p>For this example, we&#8217;ll use the Commonwealth of Australia&#8217;s model Confidentiality Agreement,\u00a0available at\u00a0http:\/\/www.business.gov.au\/IPToolkit<\/p>\n<p>Here&#8217;s what the first few\u00a0blanks look like, represented as content controls with the &#8220;No XML&#8221; AddIn&#8217;s ribbon showing in Word:<\/p>\n<p><a href=\"https:\/\/www.docx4java.org\/blog\/wp-content\/uploads\/2018\/04\/NoXMLAddIn1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-464\" src=\"https:\/\/www.docx4java.org\/blog\/wp-content\/uploads\/2018\/04\/NoXMLAddIn1.png\" alt=\"NoXMLAddIn1\" width=\"939\" height=\"484\" \/><\/a><\/p>\n<p>I had pressed the &#8220;Show tags&#8221; button to be able to see the content controls in orange above.<\/p>\n<p>Further down, there&#8217;s an optional Indemnity clause.<\/p>\n<p>Since its optional, let&#8217;s wrap that in a conditional content control.\u00a0 First, we need a question &#8220;Do you want the Indemnity&#8221;.\u00a0 It works this way because this AddIn is aimed primarily at the <em><strong>interactive<\/strong><\/em> use case, that is, a user can answer questions in their web browser to generate an instance document.<\/p>\n<p>But the resulting template can be used just as easily for the more common non-interactive \/ entirely programmatic case.<\/p>\n<p>So click the &#8220;Insert Q\/A&#8221; button.\u00a0 I did this with my cursor somewhere in the middle of the Indemnity clause.<\/p>\n<p>Fill in the form (for Multiple Choice choose yes):<\/p>\n<p><a href=\"https:\/\/www.docx4java.org\/blog\/wp-content\/uploads\/2018\/04\/qa_mcq.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-466\" src=\"https:\/\/www.docx4java.org\/blog\/wp-content\/uploads\/2018\/04\/qa_mcq.png\" alt=\"qa_mcq\" width=\"292\" height=\"392\" \/><\/a><\/p>\n<p>click next, then on the next page, choose type boolean (true\/false), then ok.<\/p>\n<p>You&#8217;ll see a content control inserted where your cursor was.\u00a0 We don&#8217;t really want that, so its a bit annoying (you can\/should delete it).\u00a0\u00a0You&#8217;ll see why we did this\u00a0just below.<\/p>\n<p>Now select the clause heading and body, and click &#8220;Wrap with Condition&#8221;.\u00a0 You&#8217;ll see something like:<\/p>\n<p><a href=\"https:\/\/www.docx4java.org\/blog\/wp-content\/uploads\/2018\/04\/condition1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-467\" src=\"https:\/\/www.docx4java.org\/blog\/wp-content\/uploads\/2018\/04\/condition1.png\" alt=\"condition1\" width=\"719\" height=\"664\" \/><\/a><\/p>\n<p>In the condition builder, define the following condition:<\/p>\n<p><a href=\"https:\/\/www.docx4java.org\/blog\/wp-content\/uploads\/2018\/04\/indemnity_condition.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-468\" src=\"https:\/\/www.docx4java.org\/blog\/wp-content\/uploads\/2018\/04\/indemnity_condition.png\" alt=\"indemnity_condition\" width=\"623\" height=\"139\" \/><\/a><\/p>\n<p>then click OK. (Now you can see why we needed to set up that question first)<\/p>\n<p>Our resulting conditional clause appears as follows:<\/p>\n<p><a href=\"https:\/\/www.docx4java.org\/blog\/wp-content\/uploads\/2018\/04\/indemnity_result.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-469\" src=\"https:\/\/www.docx4java.org\/blog\/wp-content\/uploads\/2018\/04\/indemnity_result.png\" alt=\"indemnity_result\" width=\"639\" height=\"196\" \/><\/a><\/p>\n<p>That&#8217;s all you need to do.\u00a0 We can now try generating an instance document from this template.<\/p>\n<p><strong>Document generation runtime<\/strong><\/p>\n<p>To generate a document, use docx4j code to populate an Answers object, then call Docx4J.bind. For example:<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nWordprocessingMLPackage wordMLPackage = WordprocessingMLPackage\r\n.load(new java.io.File(inputfilepath));\r\n\r\nanswers = new Answers();\r\n\r\naddAnswer(&quot;Sponsor_name_ACNABN_oW&quot;, &quot;CSIRO of Some St, Sydney&quot;)\r\naddAnswer(&quot;want__Indemnity_clause_K8&quot;, &quot;true&quot;); \/\/ or false\r\n\/\/ etc\r\n\r\nDocx4J.bind(wordMLPackage, answers, Docx4J.FLAG_BIND_INSERT_XML &amp;amp; Docx4J.FLAG_BIND_BIND_XML);\r\nDocx4J.save(wordMLPackage, new File(outputfilepath), Docx4J.FLAG_NONE);\r\n<\/pre>\n<p>where addAnswer is just:<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nprivate void addAnswer(String key, String value) {\r\nAnswer a = new Answer();\r\na.setId(key);\r\na.setValue(value);\r\nanswers.getAnswerOrRepeat().add(a);\r\n}\r\n<\/pre>\n<p>How do you know what key to use?\u00a0 Look in the answers part in the docx and use the corresponding ID (yes, you should be able to see this in the AddIn, but the reason you can&#8217;t is that for the interactive use-case, you never need to know), or you can just invoke Docx4J.bind with debug level logging enabled for org.docx4j.model.datastorage, and it will print out the relevant part.<\/p>\n<p><a href=\"https:\/\/www.docx4java.org\/blog\/wp-content\/uploads\/2018\/04\/answersPart.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-471\" src=\"https:\/\/www.docx4java.org\/blog\/wp-content\/uploads\/2018\/04\/answersPart.png\" alt=\"answersPart\" width=\"1069\" height=\"136\" \/><\/a><\/p>\n<p>That&#8217;s about it.\u00a0 If you have questions, they are probably best posted in the <a href=\"https:\/\/www.docx4java.org\/forums\/data-binding-java-f16\/\">relevant docx4j forum<\/a>\u00a0or on StackOverflow.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This blog post is a walkthrough of how to easily move from variable replacement to OpenDoPE content control data binding. Introduction Variable replacement is quite a popular way to get started generating Word documents. I guess that&#8217;s because developers expect this sort of approach to be available, and its easy: all you have to do [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[77],"tags":[],"class_list":["post-462","post","type-post","status-publish","format-standard","hentry","category-opendope"],"_links":{"self":[{"href":"https:\/\/www.docx4java.org\/blog\/wp-json\/wp\/v2\/posts\/462","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.docx4java.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.docx4java.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.docx4java.org\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.docx4java.org\/blog\/wp-json\/wp\/v2\/comments?post=462"}],"version-history":[{"count":6,"href":"https:\/\/www.docx4java.org\/blog\/wp-json\/wp\/v2\/posts\/462\/revisions"}],"predecessor-version":[{"id":475,"href":"https:\/\/www.docx4java.org\/blog\/wp-json\/wp\/v2\/posts\/462\/revisions\/475"}],"wp:attachment":[{"href":"https:\/\/www.docx4java.org\/blog\/wp-json\/wp\/v2\/media?parent=462"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.docx4java.org\/blog\/wp-json\/wp\/v2\/categories?post=462"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.docx4java.org\/blog\/wp-json\/wp\/v2\/tags?post=462"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}