Page 1 of 1

Incomplete header copy from template

PostPosted: Tue Feb 19, 2013 8:55 pm
by prsrikan
I have been facing an issue when I try to copy the header from a given template to an existing document. However, the problem is seen only with headers that are more complex than a simple text header. I have attached a sample dotx file containing the header and when I try to run the code I have written, it shows only part of the header (in this case, the line underneath it). The surprising thing is that the header xml file seen in the document to which I wish to apply the template contains the text object containing the appropriate header text, but this isn't displayed in the document.
What I have done in the code is to first remove any existing header references from the target document, and then create a new HeaderPart object, set the JaxB element to the one associated with the template's header, and finally add the default header references from the template; The code is as seen below:
Code: Select all
    public void headerMethod() throws InvalidFormatException {
        String templatePath = "..\\ComplexHeader.dotx";
        WordprocessingMLPackage wordMLPackage = getMainDoc(templatePath);
        String existingFileName = "..\\NewEmptyDoc.docx";
        WordprocessingMLPackage wordMLPackage1 = getMainDoc(existingFileName);
        MainDocumentPart mainDocumentPart1 = wordMLPackage1.getMainDocumentPart();
        //removing header references of existing doc
        removeHeaderFooterReferences(wordMLPackage1);
        List<SectionWrapper> sections = wordMLPackage.getDocumentModel().getSections();
        for(SectionWrapper sw : sections){
            HeaderFooterPolicy hfp = sw.getHeaderFooterPolicy();
            HeaderPart header = hfp.getDefaultHeader();
            Hdr hdr = header.getJaxbElement();
            HeaderPart newHeader = new HeaderPart();
            newHeader.setJaxbElement(hdr);
            newHeader.setPackage(wordMLPackage1);
            Relationship relShip = null;
            relShip = mainDocumentPart1.addTargetPart(newHeader);
            createHeaderFooterReference(wordMLPackage1,relShip);
        }
        SaveToZipFile saver = new SaveToZipFile(wordMLPackage1);
        try {
            saver.save(existingFileName);
        } catch (Docx4JException e) {
            System.out.println(e.getMessage());
        }
    }


The removal of header references is done as follows:
Code: Select all
    List<SectionWrapper> sections = wordprocessingMLPackage.getDocumentModel().getSections();
        HeaderPart header = null;
        for (SectionWrapper sw : sections) {
            header = sw.getHeaderFooterPolicy().getDefaultHeader();
            if(header == null) continue;
            removeRelationships(header);
            wordprocessingMLPackage.getMainDocumentPart().getRelationshipsPart().removeRelationship(header.getPartName());
            List<CTRel> rel =sw.getSectPr().getEGHdrFtrReferences();
            Iterator<CTRel> relIter = rel.iterator();
            while(relIter.hasNext()){
                CTRel ctRel = relIter.next();
                if (ctRel instanceof HeaderReference) {
                    HeaderReference hr = (HeaderReference) ctRel;
                    if (hr.getType().equals(HdrFtrRef.DEFAULT)) {
                        //sw.getSectPr().getEGHdrFtrReferences().remove(hr);
                        relIter.remove();
                    }
                }
            }
        }

The creation of the new header references is done in the same method as the sample code for header/footer creation:
Code: Select all
        List<SectionWrapper> sections = wordprocessingMLPackage.getDocumentModel().getSections();
        SectPr sectPr = sections.get(sections.size() - 1).getSectPr();
        // There is always a section wrapper, but it might not contain a sectPr
        if (sectPr==null ) {
            sectPr = objFac.createSectPr();
            wordprocessingMLPackage.getMainDocumentPart().addObject(sectPr);
            sections.get(sections.size() - 1).setSectPr(sectPr);
        }
        HeaderReference headerReference = objFac.createHeaderReference();
        headerReference.setId(headerRelationship.getId());
        headerReference.setType(HdrFtrRef.DEFAULT);
        //FooterReference footerReference = objFac.createFooterReference();
        //footerReference.setId(footerRelationship.getId());
        //footerReference.setType(HdrFtrRef.DEFAULT);
        sectPr.getEGHdrFtrReferences().add(headerReference);


Note: On examining the header xml files for the target document, I had seen that there were a whole set of namespaces associated that were not seen in the header xml files of the template. Could this be controlled, and does this affect the interpretation of the xml file by Microsoft Word when opening the document?
Thanks in advance!

Re: Incomplete header copy from template

PostPosted: Tue Feb 19, 2013 8:58 pm
by prsrikan
Attaching the dotx file

Re: Incomplete header copy from template

PostPosted: Tue Feb 19, 2013 10:25 pm
by jason
The header in your dotx contains a data bound content control:

Syntax: [ Download ] [ Hide ]
Using xml Syntax Highlighting
<w:hdr xmlns:ve="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml">
  <w:sdt>
    <w:sdtPr>
      <w:rPr>
        <w:rFonts w:asciiTheme="majorHAnsi" w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi" w:cstheme="majorBidi"/>
        <w:sz w:val="32"/>
        <w:szCs w:val="32"/>
      </w:rPr>
      <w:alias w:val="Title"/>
      <w:id w:val="77738743"/>
      <w:placeholder>
        <w:docPart w:val="EAE67E7D399A450DBF47756F8AAE3A13"/>
      </w:placeholder>
      <w:dataBinding w:prefixMappings="xmlns:ns0='http://schemas.openxmlformats.org/package/2006/metadata/core-properties' xmlns:ns1='http://purl.org/dc/elements/1.1/'" w:xpath="/ns0:coreProperties[1]/ns1:title[1]" w:storeItemID="{6C3C8BC8-F283-45AE-878A-BAB7291924A1}"/>
      <w:text/>
    </w:sdtPr>
    <w:sdtContent>
      <w:p w:rsidR="00615FDB" w:rsidRDefault="00615FDB">
        <w:pPr>
          <w:pStyle w:val="Header"/>
          <w:pBdr>
            <w:bottom w:val="thickThinSmallGap" w:sz="24" w:space="1" w:color="622423" w:themeColor="accent2" w:themeShade="7F"/>
          </w:pBdr>
          <w:jc w:val="center"/>
          <w:rPr>
            <w:rFonts w:asciiTheme="majorHAnsi" w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi" w:cstheme="majorBidi"/>
            <w:sz w:val="32"/>
            <w:szCs w:val="32"/>
          </w:rPr>
        </w:pPr>
        <w:r>
          <w:rPr>
            <w:rFonts w:asciiTheme="majorHAnsi" w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi" w:cstheme="majorBidi"/>
            <w:sz w:val="32"/>
            <w:szCs w:val="32"/>
          </w:rPr>
          <w:t>Complex Header</w:t>
        </w:r>
      </w:p>
    </w:sdtContent>
  </w:sdt>
  <w:p w:rsidR="00615FDB" w:rsidRDefault="00615FDB">
    <w:pPr>
      <w:pStyle w:val="Header"/>
    </w:pPr>
  </w:p>
</w:hdr>
 
Parsed in 0.005 seconds, using GeSHi 1.0.8.4


Note the line: <w:dataBinding w:prefixMappings="xmlns:ns0='http://schemas.openxmlformats.org/package/2006/metadata/core-properties' xmlns:ns1='http://purl.org/dc/elements/1.1/'" w:xpath="/ns0:coreProperties[1]/ns1:title[1]" w:storeItemID="{6C3C8BC8-F283-45AE-878A-BAB7291924A1}"/>

I suspect that /ns0:coreProperties[1]/ns1:title[1] is missing from your docx, and so resulting in no content.

Re: Incomplete header copy from template

PostPosted: Tue Feb 19, 2013 10:36 pm
by prsrikan
By missing in docx, do you mean missing in the header xml file? If so, I'm afraid that it is present there:
Code: Select all
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><w:hdr xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:ns6="http://schemas.openxmlformats.org/schemaLibrary/2006/main" xmlns:c="http://schemas.openxmlformats.org/drawingml/2006/chart" xmlns:ns8="http://schemas.openxmlformats.org/drawingml/2006/chartDrawing" xmlns:dgm="http://schemas.openxmlformats.org/drawingml/2006/diagram" xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture" xmlns:ns11="http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing" xmlns:dsp="http://schemas.microsoft.com/office/drawing/2008/diagram" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:ns15="urn:schemas-microsoft-com:office:excel" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:ns17="urn:schemas-microsoft-com:office:powerpoint" xmlns:odx="http://opendope.org/xpaths" xmlns:odc="http://opendope.org/conditions" xmlns:odq="http://opendope.org/questions" xmlns:odi="http://opendope.org/components" xmlns:odgm="http://opendope.org/SmartArt/DataHierarchy" xmlns:ns24="http://schemas.openxmlformats.org/officeDocument/2006/bibliography" xmlns:ns25="http://schemas.openxmlformats.org/drawingml/2006/compatibility" xmlns:ns26="http://schemas.openxmlformats.org/drawingml/2006/lockedCanvas"><w:sdt><w:sdtPr><w:rPr><w:rFonts w:cstheme="majorBidi" w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi" w:asciiTheme="majorHAnsi"/><w:sz w:val="32"/><w:szCs w:val="32"/></w:rPr><w:alias w:val="Title"/><w:id w:val="77738743"/><w:placeholder><w:docPart w:val="EAE67E7D399A450DBF47756F8AAE3A13"/></w:placeholder>[b]<w:dataBinding w:storeItemID="{6C3C8BC8-F283-45AE-878A-BAB7291924A1}" w:xpath="/ns0:coreProperties[1]/ns1:title[1]" w:prefixMappings="xmlns:ns0='http://schemas.openxmlformats.org/package/2006/metadata/core-properties' xmlns:ns1='http://purl.org/dc/elements/1.1/'"/>[/b]<w:text/></w:sdtPr><w:sdtContent><w:p w:rsidRDefault="00615FDB" w:rsidR="00615FDB"><w:pPr><w:pStyle w:val="Header"/><w:pBdr><w:bottom w:space="1" w:sz="24" w:themeShade="7F" w:themeColor="accent2" w:color="622423" w:val="thickThinSmallGap"/></w:pBdr><w:jc w:val="center"/><w:rPr><w:rFonts w:cstheme="majorBidi" w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi" w:asciiTheme="majorHAnsi"/><w:sz w:val="32"/><w:szCs w:val="32"/></w:rPr></w:pPr><w:r><w:rPr><w:rFonts w:cstheme="majorBidi" w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi" w:asciiTheme="majorHAnsi"/><w:sz w:val="32"/><w:szCs w:val="32"/></w:rPr><w:t>Complex Header</w:t></w:r></w:p></w:sdtContent></w:sdt><w:p w:rsidRDefault="00615FDB" w:rsidR="00615FDB"><w:pPr><w:pStyle w:val="Header"/></w:pPr></w:p></w:hdr>


<w:dataBinding w:storeItemID="{6C3C8BC8-F283-45AE-878A-BAB7291924A1}" w:xpath="/ns0:coreProperties[1]/ns1:title[1]" w:prefixMappings="xmlns:ns0='http://schemas.openxmlformats.org/package/2006/metadata/core-properties' xmlns:ns1='http://purl.org/dc/elements/1.1/'"/>

Re: Incomplete header copy from template

PostPosted: Wed Feb 20, 2013 7:19 am
by jason
No, the XPath is a reference in to the core properties part. Word ususally stores that as docProps/core.xml

Re: Incomplete header copy from template

PostPosted: Thu Feb 21, 2013 6:38 pm
by prsrikan
Thanks Jason! I obtained the DocsPropCorePart object and set its JaxB element to the JaxB object of the template and found it working fine. But on a related note, I have been unable to add headers with images inserted in them - when I try to open the document after running my code, there is an error prompt saying that Word can't open the document due to some missing/invalid parts and points out a line in document.xml which refers to the header reference. In the code fragment below, the HeaderPart header refers to the header in the template, and wordMLPackage1 and MainDocumentPArt1 refer to the WordprocessingMLPackage and the MainDocumentPart objects of the target document.
Code: Select all
        for(SectionWrapper sw : sections){
            HeaderFooterPolicy hfp = sw.getHeaderFooterPolicy();
            HeaderPart header = hfp.getDefaultHeader();
            Hdr hdr = header.getJaxbElement();
            HeaderPart newHeader = new HeaderPart();
            newHeader.setJaxbElement(hdr);
            newHeader.setPackage(wordMLPackage1);
            Relationship relShip = null;
            relShip = mainDocumentPart1.addTargetPart(newHeader);
            createHeaderFooterReference(wordMLPackage1,relShip);
            addSubParts(header,mainDocumentPart1);
        }

The addsubParts function adds all the related parts of the header of the template to the main document part of the target document by iterating through the relationship objects. Could you tell me what it is I'm missing out on? Also, I'm attaching the dotx file and the target document. Thanks again for your help!

Re: Incomplete header copy from template

PostPosted: Thu Feb 21, 2013 6:48 pm
by prsrikan
Note: I have also removed all relationships from the header of the target document, if any and have also removed the header's relationship with the main document part object before actually adding the new header references

Re: Incomplete header copy from template

PostPosted: Thu Feb 21, 2013 7:00 pm
by jason
Your addSubParts method - whatever it contains - is broken.

Re: Incomplete header copy from template

PostPosted: Thu Feb 21, 2013 7:57 pm
by prsrikan
Code: Select all
    public void addSubParts(HeaderPart mainPart,MainDocumentPart mainDocumentPart){
        RelationshipsPart rp = mainPart.getRelationshipsPart(false);
        if(rp == null){
          //there are no relationships => no sub parts to add
         return;
        //if there is a sub part add this to the part
        } else{     
          try{
            for(Relationship r : rp.getRelationships().getRelationship() ) {
              //get the part the relationship belongs to
              Part part = rp.getPart(r);     
             
              Relationship rh1 = mainDocumentPart.addTargetPart(part);
            }       
          } catch (InvalidFormatException e) {
            System.out.println(e.getMessage());
          } 
        }       
    }

Is there a need to add subparts recursively, which I haven't done in the code above?

Re: Incomplete header copy from template

PostPosted: Thu Feb 21, 2013 8:25 pm
by prsrikan
Another thing that I have noticed is the lack of namespaces in a few of the object components associated with the image in the target document, as opposed to the header xml in the template.
Template header fragment:
Code: Select all
<w:p w:rsidR="00D935D9" w:rsidRDefault="00D935D9"><w:pPr><w:pStyle w:val="Header"/></w:pPr><w:r><w:rPr><w:noProof/></w:rPr><w:drawing><wp:inline distT="0" distB="0" distL="0" distR="0"><wp:extent cx="5943600" cy="3949065"/><wp:effectExtent l="19050" t="0" r="0" b="0"/><wp:docPr id="1" name="Picture 0" descr="DSCF1599-1.JPG"/><wp:cNvGraphicFramePr><a:graphicFrameLocks xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" noChangeAspect="1"/></wp:cNvGraphicFramePr><a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"><a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture"><pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture"><pic:nvPicPr><pic:cNvPr id="0" name="DSCF1599-1.JPG"/><pic:cNvPicPr/></pic:nvPicPr><pic:blipFill><a:blip r:embed="rId1"/><a:stretch><a:fillRect/></a:stretch></pic:blipFill><pic:spPr><a:xfrm><a:off x="0" y="0"/><a:ext cx="5943600" cy="3949065"/></a:xfrm><a:prstGeom prst="rect"><a:avLst/></a:prstGeom></pic:spPr></pic:pic></a:graphicData></a:graphic></wp:inline></w:drawing></w:r></w:p><w:p w:rsidR="00D935D9" w:rsidRDefault="00D935D9"><w:pPr><w:pStyle w:val="Header"/></w:pPr></w:p>

Target document header fragment:
Code: Select all
<w:p w:rsidRDefault="00D935D9" w:rsidR="00D935D9"><w:pPr><w:pStyle w:val="Header"/></w:pPr><w:r><w:rPr><w:noProof/></w:rPr><w:drawing><wp:inline distR="0" distL="0" distB="0" distT="0"><wp:extent cy="3949065" cx="5943600"/><wp:effectExtent b="0" r="0" t="0" l="19050"/><wp:docPr descr="DSCF1599-1.JPG" name="Picture 0" id="1"/><wp:cNvGraphicFramePr><a:graphicFrameLocks noChangeAspect="true"/></wp:cNvGraphicFramePr><a:graphic><a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture"><pic:pic><pic:nvPicPr><pic:cNvPr name="DSCF1599-1.JPG" id="0"/><pic:cNvPicPr/></pic:nvPicPr><pic:blipFill><a:blip r:embed="rId1"/><a:stretch><a:fillRect/></a:stretch></pic:blipFill><pic:spPr><a:xfrm><a:off y="0" x="0"/><a:ext cy="3949065" cx="5943600"/></a:xfrm><a:prstGeom prst="rect"><a:avLst/></a:prstGeom></pic:spPr></pic:pic></a:graphicData></a:graphic></wp:inline></w:drawing></w:r></w:p><w:p w:rsidRDefault="00D935D9" w:rsidR="00D935D9"><w:pPr><w:pStyle w:val="Header"/></w:pPr></w:p>

Re: Incomplete header copy from template

PostPosted: Thu Feb 21, 2013 8:34 pm
by jason
You can often get away with just moving a part, and assuming it drags along the parts in its rels.

But Part has a method getPackage(), so it knows which pkg it belongs to.

Also, OpcPackage contains Parts which is essentially a map of the parts in the pkg.

If either of these methods will be used, you need to take care to make sure they are in sync with what you've done.

-----------------------

Run your docx output through PartsList and HeaderFooterList to see what you've created.

----------------------

Also check your createHeaderFooterReference(wordMLPackage1,relShip) does what you intend.

Re: Incomplete header copy from template

PostPosted: Fri Feb 22, 2013 9:07 pm
by prsrikan
Thanks for the help, Jason. I looked at the PartsList and found out that the part associated with the image was getting added as a sub part of the body of the main document, rather than a sub-part of the header, and so, I accordingly added all the sub-parts to the header part object instead. However, on trying to extend my code to include even and odd footers, I found out that the my code was able to create only one header xml per document. (that is, if there was a header object in the template that didn't have any content, but was the last header object considered, then my target document also had a blank header. Could you tell me what exactly creates the header xml files in the package associated with docx files?
Code for creating new header references:
Code: Select all
    public void createHeaderReference(WordprocessingMLPackage wordprocessingMLPackage, Relationship headerRelationship,int headerType) throws InvalidFormatException {
        List<SectionWrapper> sections = wordprocessingMLPackage.getDocumentModel().getSections();
        SectPr sectPr = sections.get(sections.size() - 1).getSectPr();
        // There is always a section wrapper, but it might not contain a sectPr
        if (sectPr==null ) {
            sectPr = objFac.createSectPr();
            wordprocessingMLPackage.getMainDocumentPart().addObject(sectPr);
            sections.get(sections.size() - 1).setSectPr(sectPr);
        }
        HeaderReference headerReference = objFac.createHeaderReference();
        headerReference.setId(headerRelationship.getId());
        if(headerType == 0) {
            headerReference.setType(HdrFtrRef.DEFAULT);
            System.out.println("Addition of default");
        }
        if(headerType == 1) {
            headerReference.setType(HdrFtrRef.EVEN);
            System.out.println("Addition of even");
        }
        sectPr.getEGHdrFtrReferences().add(headerReference);
    }

In my code, I have been iterating through the sections and getting the default and the even headers from the HeaderFooterPolicy object in that order, and for each of those, I am creating new HeaderPart objects, setting the JaxB element to point to that of the template, and creating header references as per the code. What am I missing? Thanks again for all your help!

Re: Incomplete header copy from template

PostPosted: Fri Feb 22, 2013 11:11 pm
by jason
It is not quick/easy to see what you are doing from this various snippets of code.

Maybe you should post a complete standalone .java file containing your code, plus associated input docx.

That way, someone - maybe me - can easily run it in an IDE to see what is happening, and give you feedback.

Re: Incomplete header copy from template

PostPosted: Sat Feb 23, 2013 12:03 am
by prsrikan
PFA the required. Thanks!

Re: Incomplete header copy from template

PostPosted: Fri Mar 01, 2013 4:00 am
by prsrikan
Jason,
I seem to have figured out why the headers were getting overwritten and I used
Code: Select all
addTargetPart(newHeader,RelationshipsPart.AddPartBehaviour.RENAME_IF_NAME_EXISTS)
to overcome this. I also came across a way of programmatically setting the option to display odd and even headers (in CTSettings.java). However, I was unable to find something similar for the first page header. Could you point this out to me? Thanks for all your help so far!

Re: Incomplete header copy from template

PostPosted: Thu Mar 07, 2013 10:15 pm
by jason
Hi, I take it this is all resolved for you now, with your other post re titlePg?