Changeset 1731 for trunk/docx4j/src/main


Ignore:
Timestamp:
12/13/11 14:02:25 (5 months ago)
Author:
jharrop
Message:

FieldRef? model - suitable for MERGEFIELD

Location:
trunk/docx4j/src/main/java/org/docx4j/model/fields
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/docx4j/src/main/java/org/docx4j/model/fields/FieldRef.java

    r1727 r1731  
    11package org.docx4j.model.fields; 
    22 
     3import javax.xml.bind.JAXBElement; 
     4 
     5import org.docx4j.XmlUtils; 
     6import org.docx4j.jaxb.Context; 
     7import org.docx4j.wml.P; 
    38import org.docx4j.wml.R; 
     9import org.docx4j.wml.Text; 
    410 
    511/** 
     
    239245 * In general, you can "canonicalise" the field representation 
    240246 * to be  
    241  * (i)   instructions, contained within a single run (dropping rPr) 
     247 * (i)   instructions, contained within a single run  
    242248 * (ii)  results, immediately following, though not nec just as following siblings 
    243249 * (iii) the final <w:fldChar w:fldCharType="end"/> 
     
    253259public class FieldRef { 
    254260         
    255         private R fieldParent; 
     261        private P parent; 
     262        public P getParent() { 
     263                return parent; 
     264        } 
     265        public void setParent(P parent) { 
     266                this.parent = parent; 
     267        } 
     268 
    256269         
     270        /** 
     271         * The run  
     272         *  
     273         *       <w:r> 
     274                <w:fldChar w:fldCharType="begin"/> 
     275                <w:instrText xml:space="preserve"> ... </w:instrText> 
     276                <w:fldChar w:fldCharType="separate"/> 
     277            </w:r> 
     278             
     279        Store a reference to it so we can delete it. 
     280         */ 
     281        private R beginRun; 
     282        public R getBeginRun() { 
     283                return beginRun; 
     284        } 
     285        public void setBeginRun(R beginRun) { 
     286                this.beginRun = beginRun; 
     287        } 
     288 
     289        /** 
     290         * The run  
     291         *  
     292            <w:r> 
     293                <w:fldChar w:fldCharType="end"/> 
     294            </w:r> 
     295             
     296        Store a reference to it so we can delete it. 
     297         */ 
     298        private R endRun; 
     299        public R getEndRun() { 
     300                return endRun; 
     301        } 
     302        public void setEndRun(R endRun) { 
     303                this.endRun = endRun; 
     304        } 
    257305         
     306        private JAXBElement<Text> instrText; 
     307        public JAXBElement<Text> getInstrText() { 
     308                return instrText; 
     309        } 
     310        public void setInstrText(JAXBElement<Text> instrText) { 
     311                this.instrText = instrText; 
     312        } 
     313 
     314        private R resultsSlot; 
     315        public R getResultsSlot() { 
     316                return resultsSlot; 
     317        } 
     318        public void setResultsSlot(R resultsSlot) { 
     319                this.resultsSlot = resultsSlot; 
     320        } 
     321         
     322        public void setResult(String val) { 
     323                 
     324                Text t = null; 
     325                if (resultsSlot.getContent().size()==0) { 
     326                        t = Context.getWmlObjectFactory().createText(); 
     327                        resultsSlot.getContent().add(t); 
     328                } else { 
     329                        // Assume child Text 
     330                        t = (Text)XmlUtils.unwrap(resultsSlot.getContent().get(0)); 
     331                } 
     332                t.setValue(val);                 
     333        } 
    258334 
    259335} 
  • trunk/docx4j/src/main/java/org/docx4j/model/fields/FieldsPreprocessor.java

    r1727 r1731  
    22 
    33import java.io.IOException; 
     4import java.util.ArrayList; 
    45import java.util.HashMap; 
     6import java.util.List; 
    57import java.util.Map; 
    68 
    79import javax.xml.bind.JAXBContext; 
     10import javax.xml.bind.JAXBElement; 
    811import javax.xml.bind.Unmarshaller; 
     12import javax.xml.namespace.QName; 
    913import javax.xml.transform.Source; 
    1014import javax.xml.transform.Templates; 
     
    2630import org.docx4j.wml.P; 
    2731import org.docx4j.wml.R; 
     32import org.docx4j.wml.RPr; 
    2833import org.docx4j.wml.STFldCharType; 
     34import org.docx4j.wml.Text; 
    2935 
    3036/** 
     
    4248         
    4349        private static Logger log = Logger.getLogger(FieldsPreprocessor.class);          
     50 
     51    private final static QName _RInstrText_QNAME = new QName("http://schemas.openxmlformats.org/wordprocessingml/2006/main",  
     52                "instrText"); 
    4453         
    4554        static Templates xslt;                   
     
    100109//      } 
    101110         
    102         public static P canonicalise(P p) { 
     111        public static P canonicalise(P p, List<FieldRef> fieldRefs) { 
    103112                /* 
    104113                 * Result is something like: 
     
    126135                R newR = Context.getWmlObjectFactory().createR(); 
    127136                 
     137                RPr fieldRPr = null; 
     138                 
     139                FieldRef currentField = null; 
     140                 
    128141                for (Object o : p.getContent() ) { 
    129142                         
    130143                        if ( o instanceof R ) { 
    131  
    132                                 for (Object o2 : ((R)o).getContent() ) { 
     144                                 
     145                                R existingRun = (R)o; 
     146                                for (Object o2 : existingRun.getContent() ) { 
    133147 
    134148                                        if (isCharType(o2, STFldCharType.BEGIN)) { 
     
    140154                                                        if (newR.getContent().size()>0) { 
    141155                                                                newP.getContent().add(newR); 
     156                                                                 
     157                                                                newR.setRPr(existingRun.getRPr() ); // if any 
    142158                                                        } 
    143                                                          
     159 
    144160                                                        newR = Context.getWmlObjectFactory().createR(); 
    145161                                                        newR.getContent().add(o2); 
     162                                                         
     163                                                        // Setup our FieldRef object - only top level fields for now 
     164                                                        currentField = new FieldRef();                                                   
     165                                                        fieldRefs.add(currentField); 
     166                                                        currentField.setParent(newP);                                                    
     167                                                        currentField.setBeginRun(newR); 
     168 
    146169                                                } 
    147170                                        } 
     
    152175                                                        // Top level field end - gets its own w:r 
    153176                                                        newP.getContent().add(newR); 
     177                                                         
    154178                                                        newR = Context.getWmlObjectFactory().createR(); 
    155179                                                        newR.getContent().add(o2); 
     180                                                        newP.getContent().add(newR); 
     181                                                         
     182                                                        currentField.setEndRun(newR); 
     183                                                         
    156184                                                        newR = Context.getWmlObjectFactory().createR(); 
    157185                                                } else { 
     
    165193                                                        newP.getContent().add(newR); 
    166194                                                        newR = Context.getWmlObjectFactory().createR(); 
     195                                                         
     196                                                        // May as well set this; we'll insert our result into 
     197                                                        // this (or recreate it). 
     198                                                        newR.setRPr(fieldRPr );  
     199                                                         
     200                                                        currentField.setResultsSlot(newR); // FIXME: ensure newR is actually added! 
     201                                                         
    167202                                                } 
     203                                        } else if (o2 instanceof JAXBElement 
     204                                                        && ((JAXBElement)o2).getName().equals(_RInstrText_QNAME)) { 
     205                                                 
     206                                                currentField.setInstrText( (JAXBElement<Text>)o2); 
     207 
     208                                                newR.getContent().add(o2);       
     209                                                 
     210                                                fieldRPr = existingRun.getRPr(); 
     211                                                newR.setRPr(fieldRPr); 
    168212                                                 
    169213                                        } else { 
     
    227271                WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load( 
    228272                                new java.io.File( 
    229                                                 System.getProperty("user.dir") + "/simpledatefield.docx")); 
     273                                                System.getProperty("user.dir") + "/mergefield1.docx")); 
    230274                 
    231275                complexifyFields(wordMLPackage.getMainDocumentPart() ); 
     
    237281                new TraversalUtil(wordMLPackage.getMainDocumentPart().getContent(), fl); 
    238282                log.info("Found " + fl.starts.size() + " fields "); 
     283                 
     284                List<FieldRef> fieldRefs = new ArrayList<FieldRef>(); 
     285                 
    239286                for( P p : fl.starts) { 
    240287                        int index = ((ContentAccessor)p.getParent()).getContent().indexOf(p); 
    241                         P newP = canonicalise(p); 
     288                        P newP = canonicalise(p, fieldRefs); 
    242289                        System.out.println("NewP length: " + newP.getContent().size() ); 
    243290                        ((ContentAccessor)p.getParent()).getContent().set(index, newP); 
    244291                } 
    245  
     292                 
     293                // Prove we can put something into the results 
     294                int counter = 0; 
     295                for (FieldRef fr : fieldRefs) { 
     296                        fr.setResult("Result" + counter); 
     297                        counter++; 
     298                         
     299                        // If doing an actual mail merge, the begin-separate run is removed, as is the end run 
     300                        fr.getParent().getContent().remove(fr.getBeginRun()); 
     301                        fr.getParent().getContent().remove(fr.getEndRun());                      
     302                } 
     303                 
    246304                System.out.println(XmlUtils.marshaltoString(wordMLPackage.getMainDocumentPart().getJaxbElement(), true, true)); 
    247305                 
    248306                wordMLPackage.save(new java.io.File( 
    249                                 System.getProperty("user.dir") + "/simpledatefield-COMPLEX.docx") ); 
     307                                System.getProperty("user.dir") + "/mergefield1-OUT.docx") ); 
    250308                 
    251309                 
  • trunk/docx4j/src/main/java/org/docx4j/model/fields/FieldsSimpleToComplex.xslt

    r1727 r1731  
    5656  <xsl:template match="w:fldSimple" > 
    5757        <w:r> 
     58          <!--  Keep any rPr, so we can preserve bold, italic, underline etc --> 
     59          <xsl:copy-of select="w:r/w:rPr" /> 
     60       
    5861      <w:fldChar w:fldCharType="begin"/> 
    5962        <w:instrText xml:space="preserve"><xsl:value-of select="@w:instr"></xsl:value-of> </w:instrText> 
Note: See TracChangeset for help on using the changeset viewer.