Page 1 of 1

PPTX is not refreshed after addition of new elements

PostPosted: Tue Jan 29, 2019 4:06 am
by aashish
Hello,

I'm facing an issue while performing PPTX manipulation.
The problem statement is to generate the table of contents, add N number of paragraphs (CTTextParagraph) into existing text container (txBody). The presentation will have the first paragraph to maintain style and formatting.

Approach:
1. Create the List<JAXBAssociation> for the first paragraph
2. Perform clone operation and create n number of paragraphs and add into new List
3. Get the txBody through xpathExpr and JAXBAssociation and add all cloned paragraph
4 Perform text replacement operation

Output:
1. It generates the new PPTX and I can see the expected output
2. However, the real problem is I have to restrict this operation if the text goes beyond the text-container (overflow condition) but I couldn't any flag or setting from which I can derive the boundary conditions.
3. The <p:spPr> properties remains same
<p:spPr>
<a:xfrm>
<a:off y="1825625" x="838199"/>
<a:ext cy="2953765" cx="8932317"/>
</a:xfrm>
</p:spPr>

4. Another issue I believe PresentationMLPackage holds the older reference of paragraphs even after I have added all cloned list. I tried to refresh XML with getJAXBAssociationsForXPath method but it doesn't work.

Here is my code snippet

Code: Select all
        List<JAXBAssociation> txBodyList = slidePart.getJAXBAssociationsForXPath(
                ".//p:cSld/p:spTree/p:sp/p:txBody/a:p/a:r/a:t[contains(text(),'"+ key +"')]/ancestor::p:txBody",
                false);
        if(!txBodyList.isEmpty() && txBodyList.get(0).getJaxbObject() instanceof CTTextBody) {
            CTTextBody s = (CTTextBody) txBodyList.get(0).getJaxbObject();
            List<CTTextParagraph> txParaList = s.getP();
            txParaList.addAll(clonedPList);
             
            for(CTTextParagraph p: txParaList) {
                List<Object> txRunList = p.getEGTextRun();
                for (Object oT: txRunList) {
                    String text = ((CTRegularTextRun) oT).getT();

                    if (text.contains(key)) {
                        // text replace logic
                    }
                }
            }

        }


I have spent a good amount of time to restrict the overflow condition but couldn't find the proper solution.
Need your expert opinion and do let me know if you think this information is not enough to understand the problem.

Thanks,
AA

Re: PPTX is not refreshed after addition of new elements

PostPosted: Tue Jan 29, 2019 6:46 am
by jason
1. Create the List<JAXBAssociation> for the first paragraph
2. Perform clone operation and create n number of paragraphs and add into new List
3. Get the txBody through xpathExpr and JAXBAssociation and add all cloned paragraph


You need to invoke updateXML https://docs.oracle.com/javase/8/docs/a ... ng.Object-

Changes in JAXB object tree are updated in its associated XML parse tree.


In docx4j, you can do this with refreshXmlFirst=true in
https://github.com/plutext/docx4j/blob/ ... .java#L197 or the method getJAXBAssociationsForXPath which you call.

As per the javadoc:

Code: Select all
    * If you have modified your JAXB objects (eg added or changed a
    * w:p paragraph), you need to update the association. The problem
    * is that this can only be done ONCE, owing to a bug in JAXB:
    * see https://github.com/javaee/jaxb-v2/issues/459
    *
    * So this is left for you to choose to do via the refreshXmlFirst parameter.


Regarding https://github.com/javaee/jaxb-v2/issues/459 you could workaround this by

  • Switching from Oracle JAXB to MOXy? or
  • calling setJaxbElement(getJaxbElement()) then getBinder() which would re-establish synchronization between XML infoset nodes and JAXB objects.