Page 1 of 1

Iterating Over Properties

PostPosted: Wed Jan 16, 2019 2:19 am
by dmekonnen
Greetings,

I would like to iterate over all w:rPr elements, which may have more than one parent element. What is the best way to obtain a list of all RPr class instances? I had initially tried with ClassFinder but obtained an empty list. Would XPath work here? The Cheat Sheet linked from github README.md makes a warning about a limitation with the Jaxb API and XPath, but the sheet itself is nearly 6 years old and the warning may no longer be applicable.

thanks!

-Daniel

Re: Iterating Over Properties

PostPosted: Thu Jan 17, 2019 6:42 am
by jason
Here's an example using Traverse:

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
        public static void main(String[] args) throws Exception {

                String inputfilepath =  System.getProperty("user.dir") + "/sample-docs/word/sample-docx.docx";

                               
                WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(new java.io.File(inputfilepath));         
                MainDocumentPart documentPart = wordMLPackage.getMainDocumentPart();
                               
                PropertiesFinder finder = new PropertiesFinder();
                new TraversalUtil(documentPart.getContent(), finder);
               
                // Results
                System.out.println("got " + finder.results.size()  );
               
                for (Object o : finder.results) {
                                               
                        System.out.println( XmlUtils.marshaltoString(o, true, true));
                       
                        // You can access the parent Run
                        System.out.println( "parent: " + ((Child)o).getParent().getClass().getName() );
                }
                                                               
        }
       
        public static class PropertiesFinder extends CallbackImpl {
                 
                        public List<RPr> results = new ArrayList<RPr>();
                       
                        @Override
                        public List<Object> apply(Object o) {
                               
                                if (o instanceof R
                                                && ((R)o).getRPr()!=null ) {

                                        results.add( ((R)o).getRPr() );
                                }
                                return null;
                        }
        }      
 
Parsed in 0.017 seconds, using GeSHi 1.0.8.4


Alternatively you could see whether XPath works for you. See the comments in https://github.com/plutext/docx4j/blob/ ... Query.java for possible limitations.

You can use xpath "//w:rPr".

You may need to do some research / experimentation to see whether the warning apply to your use case. If you do, please let us know what you find (including which JAXB you are using and/or Java version).

Re: Iterating Over Properties

PostPosted: Thu Jan 17, 2019 7:33 am
by jason
Just to add to my reply, the reason ClassFinder doesn't find your RPr objects is that it traverses the content lists. (Objects typically have a properties object and a content list).

The approach I illustrated would work equally for paragraph properties (PPr), and table properties (inc TrPr and TcPr).

XPath, regarding https://github.com/javaee/jaxb-v2/issues/459 (ie if you are not using MOXy) and it affects your use case, I guess you could workaround this by calling setJaxbElement(getJaxbElement()) then getBinder() which would re-establish synchronization between XML infoset nodes and JAXB objects.

Re: Iterating Over Properties

PostPosted: Tue Jan 22, 2019 10:41 pm
by dmekonnen
Jason,

Thank you for the response, it was very insightful and I've created a couple finders that expand on your example that allowed me to complete my project. I really appreciate the great support :D

-Daniel