{"id":482,"date":"2019-01-03T09:01:43","date_gmt":"2019-01-02T23:01:43","guid":{"rendered":"https:\/\/www.docx4java.org\/blog\/?p=482"},"modified":"2019-01-03T09:38:30","modified_gmt":"2019-01-02T23:38:30","slug":"opendope-and-xpath-2-03-0","status":"publish","type":"post","link":"https:\/\/www.docx4java.org\/blog\/2019\/01\/opendope-and-xpath-2-03-0\/","title":{"rendered":"OpenDoPE and XPath 2.0\/3.0"},"content":{"rendered":"<p>Docx4j generally uses Apache XPath (org.apache.xpath),\u00a0from the Xalan 2.7.2 jar.\u00a0 (docx4j uses Xalan plus Xalan-specific extension functions for XSLT in\u00a0various places including HTML export and OpenDoPE processing).<\/p>\n<p>There are 2 main places where docx4j uses XPath:<\/p>\n<ol>\n<li><strong>JaxbXmlPartXPathAware<\/strong> contains method <strong>getJAXBNodesViaXPath<\/strong>, which &#8211; thanks to JAXB&#8217;s concept of a <strong>binder<\/strong> &#8211; you can use to select objects (say P objects) in your MainDocumentPart<\/li>\n<li><strong>OpenDoPE content control data binding<\/strong>: XPath is central to content control data binding (binding document content to XML data via XPath).<\/li>\n<\/ol>\n<p>XPath 2.0 became a W3C Rec in 2007;\u00a0 XPath 3.0\u00a0became a W3C Rec in 2014.<\/p>\n<p>Sadly, Apache XPath has languished at XPath 1.0 level:\u00a0<a href=\"https:\/\/intellectualcramps.wordpress.com\/2009\/01\/12\/xerces-getting-xpath-2-0-support\/\" rel=\"noopener\" target=\"_blank\">https:\/\/intellectualcramps.wordpress.com\/2009\/01\/12\/xerces-getting-xpath-2-0-support\/<\/a> and <a href=\"http:\/\/apache-xml-project.6118.n7.nabble.com\/XSLT-2-0-td20898.html\" rel=\"noopener\" target=\"_blank\">http:\/\/apache-xml-project.6118.n7.nabble.com\/XSLT-2-0-td20898.html<\/a> <\/p>\n<p>Saxon, in contrast, has supported XPath 2.0 for ages, and also supports 3.1.<\/p>\n<p>In docx4j 6.1.0 we made it easy for you to try\u00a0Saxon for case 1 (JaxbXmlPartXPathAware\u00a0getJAXBNodesViaXPath):<\/p>\n<p>Step 1: add Saxon to your classpath, for example (Maven):<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;dependency&gt;\r\n  &lt;groupId&gt;net.sf.saxon&lt;\/groupId&gt;\r\n  &lt;artifactId&gt;Saxon-HE&lt;\/artifactId&gt;\r\n  &lt;version&gt;9.9.0-2&lt;\/version&gt;\r\n&lt;\/dependency&gt;\r\n<\/pre>\n<p>Step 2: add the following early in your code:<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nXPathFactoryUtil.setxPathFactory(new net.sf.saxon.xpath.XPathFactoryImpl())\r\n<\/pre>\n<p>In docx4j 6.1.0,\u00a0this only affects\u00a0case 1.\u00a0\u00a0OpenDoPE content control data binding would still use Apache XPath.<\/p>\n<p>In docx4j 8.0.0,\u00a0Saxon would also be used for\u00a0OpenDoPE content control data binding.<\/p>\n<h2>An example: date comparison<\/h2>\n<p>You can add\u00a0an OpenDoPE conditional content control, in which the content is inserted only if XPath &#8220;<strong>xs:date(\/invoice\/date) > xs:date(&#8216;2018-12-31&#8217;)<\/strong>&#8221; is true.\u00a0 (date comparison is harder in XPath 1.0:\u00a0https:\/\/stackoverflow.com\/questions\/4347320\/xpath-dates-comparison )<\/p>\n<p>For this to work, you need the prefix mapping\u00a0xmlns:xs=&#8217;http:\/\/www.w3.org\/2001\/XMLSchema&#8217;, so your XPath in the OpenDoPE XPaths path would look something like:<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;xpath id=&quot;dateGt&quot;&gt;\r\n  &lt;dataBinding xpath=&quot;xs:date(\/invoice\/date) &amp;amp;gt; xs:date('2018-12-31')&quot; \r\n prefixMappings=&quot;xmlns:xs='http:\/\/www.w3.org\/2001\/XMLSchema'&quot; \r\n storeItemID=&quot;{8B049945-9DFE-4726-9DE9-CF5691E53858}&quot;\/&gt;\r\n&lt;\/xpath&gt;\r\n<\/pre>\n<p>(for now, you need to manually edit the zipped docx to add that; I&#8217;ll update the authoring tools to do it in due course)<\/p>\n<p>You can try this example right away:<\/p>\n<ul>\n<li>get\u00a0a docx4j 8.0 nightly:\u00a0https:\/\/docx4java.org\/docx4j\/docx4j-8.0.0-SNAPSHOT-20190102.jar<\/li>\n<li>add Saxon (as above)<\/li>\n<li>bind\u00a0invoice_Saxon_XPath2.docx\u00a0from <a href=\"https:\/\/github.com\/plutext\/docx4j\/blob\/VERSION_8_0_0\/sample-docs\/word\/databinding\/invoice_Saxon_XPath2.docx\" rel=\"noopener\" target=\"_blank\">https:\/\/github.com\/plutext\/docx4j\/blob\/VERSION_8_0_0\/sample-docs\/word\/databinding\/invoice_Saxon_XPath2.docx<\/a> using\u00a0<a class=\"link-gray-dark\" title=\"src\/samples\/docx4j\/org\/docx4j\/samples\/ContentControlBindingExtensions.java\" href=\"https:\/\/github.com\/plutext\/docx4j\/commit\/1bd5f8375525c2f3f22eef33077b593379391b77#diff-d4ba0f6646f78b8164c0a607f16487dd\">ContentControlBindingExtensions.java<\/a><\/li>\n<\/ul>\n<p>Try changing the date in <a href=\"https:\/\/github.com\/plutext\/docx4j\/commit\/1bd5f8375525c2f3f22eef33077b593379391b77#diff-ee309a7830f15544016fc99c29138773R3\" rel=\"noopener\" target=\"_blank\">invoice-data.xml<\/a> to say, 2018-01-15, then observe the affect on the output docx.<\/p>\n<p>Just to re-iterate, you need Saxon for this to work. Xalan&#8217;s XPath will cause an exception.<\/p>\n<p><a href=\"https:\/\/github.com\/eclipse\/webtools.sourceediting\/blob\/master\/xpath\/bundles\/org.eclipse.wst.xml.xpath2.processor\/pom.xml\" rel=\"noopener\" target=\"_blank\">org.eclipse.wst.xml.xpath2.processor<\/a> is an interesting possible alternative, but it is not in Maven Central, not as well-known as Saxon, and  possibly not so easy to get support?<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Docx4j generally uses Apache XPath (org.apache.xpath),\u00a0from the Xalan 2.7.2 jar.\u00a0 (docx4j uses Xalan plus Xalan-specific extension functions for XSLT in\u00a0various places including HTML export and OpenDoPE processing). There are 2 main places where docx4j uses XPath: JaxbXmlPartXPathAware contains method getJAXBNodesViaXPath, which &#8211; thanks to JAXB&#8217;s concept of a binder &#8211; you can use to select [&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":[102,108,107],"class_list":["post-482","post","type-post","status-publish","format-standard","hentry","category-opendope","tag-opendope","tag-saxon","tag-xpath"],"_links":{"self":[{"href":"https:\/\/www.docx4java.org\/blog\/wp-json\/wp\/v2\/posts\/482","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=482"}],"version-history":[{"count":10,"href":"https:\/\/www.docx4java.org\/blog\/wp-json\/wp\/v2\/posts\/482\/revisions"}],"predecessor-version":[{"id":492,"href":"https:\/\/www.docx4java.org\/blog\/wp-json\/wp\/v2\/posts\/482\/revisions\/492"}],"wp:attachment":[{"href":"https:\/\/www.docx4java.org\/blog\/wp-json\/wp\/v2\/media?parent=482"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.docx4java.org\/blog\/wp-json\/wp\/v2\/categories?post=482"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.docx4java.org\/blog\/wp-json\/wp\/v2\/tags?post=482"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}