package org.docx4j.samples;
import java.io.File;
import java.util.List;
import javax.xml.bind.JAXBException;
import org.docx4j.XmlUtils;
import org.docx4j.jaxb.XPathBinderAssociationIsPartialException;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.JaxbXmlPartXPathAware;
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
public class XPathOverDir {
/**
* Example of how to find an object in document.xml
* via XPath.
*
* As explained in Getting Started, there are limitations
* in the JAXB reference implementation which make this
* approach buggy:
*
* 1. the xpath expressions are evaluated against the XML
* document as it was when first opened in docx4j. You
* can update the associated XML document once only, by
* passing true into getJAXBNodesViaXPath. Updating it again
* (with current JAXB 2.1.x or 2.2.x) will cause an error.
*
* 2. For some objects,JAXB can’t get parent (with getParent)
*
* 3. For some document, JAXB can’t set up the XPath at all!
*
* If these problems affect you, you could try using
* MOXy as your JAXB implementation (which docx4j supports
* as from forthcoming docx4j 3.0). See
* http://www.docx4java.org/forums/docx-java-f6/moxy-t1242.html
*
* Alternatively, the tried and tested approach is
* to use TraversalUtil;
* see the OpenMainDocumentAndTraverse sample.
*
*/
public static void main(String[] args) throws Exception {
String inputdir = System.getProperty("user.dir") + "/dd/";
File dir = new File(inputdir);
if (dir.isDirectory()) {
String[] files = dir.list();
for (int i = 0; i<files.length; i++ ) {
System.out.println("\n" + files[i] + "\n\n");
if (files[i].endsWith("docx")) {
WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(new java.io.File(inputdir + "/" + files[i]));
MainDocumentPart documentPart = wordMLPackage.getMainDocumentPart();
xpathQuery(documentPart, "//w:fldChar[count(w:ffData)=1]");
}
}
}
}
private static void xpathQuery(JaxbXmlPartXPathAware part, String xpath) throws XPathBinderAssociationIsPartialException, JAXBException {
// String xpath = "//w:t[contains(text(),'scaled')]";
//String xpath = "//w:r[w:t[contains(text(),'scaled')]]";
List<Object> list = part.getJAXBNodesViaXPath(xpath, false);
System.out.println("got " + list.size() + " matching " + xpath );
for (Object o : list) {
//System.out.println(o.getClass().getName() );
Object o2 = XmlUtils.unwrap(o);
// this is ok, provided the results of the Callback
// won't be marshalled
if (o2 instanceof org.docx4j.wml.Text) {
org.docx4j.wml.Text txt = (org.docx4j.wml.Text)o2;
System.out.println( txt.getValue() );
// Demonstrate the getParent bug
//Object parent = txt.getParent();
//System.out.println( "parent: " + XmlUtils.unwrap(parent).getClass().getName() );
} else {
System.out.println( XmlUtils.marshaltoString(o, true, true));
}
}
}
}