Skip to content

Commit e98ce9a

Browse files
committed
databinding: support w14 checkbox
1 parent 5ebad71 commit e98ce9a

File tree

2 files changed

+187
-4
lines changed

2 files changed

+187
-4
lines changed

src/main/java/org/docx4j/model/datastorage/BindingTraverserXSLT.java

Lines changed: 157 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,16 @@
5757
import org.docx4j.openpackaging.parts.relationships.RelationshipsPart;
5858
import org.docx4j.relationships.Relationship;
5959
import org.docx4j.utils.ResourceUtils;
60+
import org.docx4j.w14.CTSdtCheckbox;
61+
import org.docx4j.w14.CTSdtCheckboxSymbol;
6062
import org.docx4j.wml.CTAltChunk;
6163
import org.docx4j.wml.CTBookmark;
64+
import org.docx4j.wml.CTDataBinding;
6265
import org.docx4j.wml.CTSdtDate;
6366
import org.docx4j.wml.Color;
6467
import org.docx4j.wml.P;
6568
import org.docx4j.wml.R;
69+
import org.docx4j.wml.RFonts;
6670
import org.docx4j.wml.RPr;
6771
import org.docx4j.wml.SdtPr;
6872
import org.docx4j.wml.Style;
@@ -1068,7 +1072,7 @@ public static DocumentFragment xpathInjectImage(WordprocessingMLPackage wmlPacka
10681072

10691073

10701074
// Now add the inline in w:p/w:r/w:drawing
1071-
org.docx4j.wml.ObjectFactory factory = new org.docx4j.wml.ObjectFactory();
1075+
org.docx4j.wml.ObjectFactory factory = Context.getWmlObjectFactory();
10721076
org.docx4j.wml.Tc tc = factory.createTc();
10731077
org.docx4j.wml.P p = factory.createP();
10741078
if (sdtParent.equals("tr")) {
@@ -1258,7 +1262,7 @@ public static DocumentFragment nullResultParagraph(String sdtParent, String mess
12581262

12591263
try
12601264
{
1261-
org.docx4j.wml.ObjectFactory factory = new org.docx4j.wml.ObjectFactory();
1265+
org.docx4j.wml.ObjectFactory factory = Context.getWmlObjectFactory();
12621266
org.docx4j.wml.R run = factory.createR();
12631267
org.docx4j.wml.Text text = factory.createText();
12641268
text.setValue(message);
@@ -1346,7 +1350,7 @@ public static DocumentFragment xpathDate(WordprocessingMLPackage wmlPackage,
13461350
}
13471351

13481352
Format formatter = new SimpleDateFormat(format);
1349-
org.docx4j.wml.ObjectFactory factory = new org.docx4j.wml.ObjectFactory();
1353+
org.docx4j.wml.ObjectFactory factory = Context.getWmlObjectFactory();
13501354

13511355
Date date;
13521356
RPr rPr = null;
@@ -1497,6 +1501,156 @@ public static DocumentFragment convertFlatOPC(
14971501

14981502
}
14991503

1504+
/**
1505+
* Support for w14 checkbox.
1506+
*
1507+
* @since 3.2.2
1508+
*/
1509+
public static DocumentFragment w14Checkbox(WordprocessingMLPackage wmlPackage,
1510+
JaxbXmlPart sourcePart,
1511+
Map<String, CustomXmlPart> customXmlDataStorageParts,
1512+
NodeIterator sdtPrNodeIt,
1513+
String sdtParent,
1514+
String contentChild) {
1515+
1516+
SdtPr sdtPr = null;
1517+
Node sdtPrNode = sdtPrNodeIt.nextNode();
1518+
if (sdtPrNode==null) {
1519+
log.error("Couldn't get sdtPr!");
1520+
return null;
1521+
} else {
1522+
try {
1523+
sdtPr = (SdtPr)XmlUtils.unmarshal(sdtPrNode, Context.jc, SdtPr.class);
1524+
} catch (JAXBException e) {
1525+
log.error(e.getMessage(), e);
1526+
}
1527+
}
1528+
1529+
/*
1530+
<w14:checkbox>
1531+
<w14:checked w14:val="0"/>
1532+
<w14:checkedState w14:val="2612" w14:font="MS Gothic"/>
1533+
<w14:uncheckedState w14:val="2610" w14:font="MS Gothic"/>
1534+
</w14:checkbox>
1535+
*/
1536+
CTSdtCheckbox sdtCheckbox = (CTSdtCheckbox)sdtPr.getByClass(CTSdtCheckbox.class);
1537+
1538+
CTDataBinding dataBinding = sdtPr.getDataBinding();
1539+
CustomXmlPart part = customXmlDataStorageParts.get(dataBinding.getStoreItemID().toLowerCase());
1540+
1541+
if (part==null) {
1542+
log.error("Couldn't locate part by storeItemId " + dataBinding.getStoreItemID());
1543+
return null;
1544+
}
1545+
1546+
try {
1547+
String r = part.xpathGetString(dataBinding.getXpath(), dataBinding.getPrefixMappings());
1548+
log.debug(dataBinding.getXpath() + " yielded result " + r);
1549+
if (r==null) return nullResultParagraph(sdtParent, "[missing!]");
1550+
1551+
org.docx4j.wml.ObjectFactory factory = Context.getWmlObjectFactory();
1552+
1553+
org.docx4j.wml.Text text = factory.createText();
1554+
1555+
// At present we ignore the checkedState and uncheckedState, except to warn..
1556+
if (r.equals("true") || r.equals("1")) {
1557+
1558+
if (log.isWarnEnabled() && sdtCheckbox.getCheckedState()!=null) {
1559+
CTSdtCheckboxSymbol sdtCheckboxSymbol = sdtCheckbox.getCheckedState();
1560+
if (sdtCheckboxSymbol.getVal()!=null
1561+
&& !sdtCheckboxSymbol.getVal().equals("2612") ) {
1562+
log.warn("TODO: handle checkedState " + sdtCheckboxSymbol.getVal());
1563+
}
1564+
}
1565+
text.setValue("☒");
1566+
1567+
} else { // Word treats everything else as false
1568+
1569+
if (log.isWarnEnabled() && sdtCheckbox.getUncheckedState()!=null) {
1570+
CTSdtCheckboxSymbol sdtCheckboxSymbol = sdtCheckbox.getUncheckedState();
1571+
if (sdtCheckboxSymbol.getVal()!=null
1572+
&& !sdtCheckboxSymbol.getVal().equals("2610") ) {
1573+
log.warn("TODO: handle uncheckedState " + sdtCheckboxSymbol.getVal());
1574+
}
1575+
}
1576+
1577+
text.setValue("☐");
1578+
}
1579+
1580+
/*
1581+
<w:p>
1582+
<w:r>
1583+
<w:rPr>
1584+
<w:rFonts w:ascii="MS Gothic" w:eastAsia="MS Gothic" w:hAnsi="MS Gothic" w:hint="eastAsia"/>
1585+
</w:rPr>
1586+
<w:t>☐</w:t>
1587+
</w:r>
1588+
</w:p>
1589+
*/
1590+
org.docx4j.wml.P p = factory.createP();
1591+
1592+
org.docx4j.wml.R run = factory.createR();
1593+
RPr rpr = factory.createRPr();
1594+
RFonts rfonts = factory.createRFonts();
1595+
rpr.setRFonts(rfonts);
1596+
rfonts.setEastAsia( "MS Gothic");
1597+
rfonts.setHint(org.docx4j.wml.STHint.EAST_ASIA);
1598+
rfonts.setHAnsi( "MS Gothic");
1599+
rfonts.setAscii( "MS Gothic");
1600+
run.setRPr(rpr);
1601+
1602+
run.getContent().add(text);
1603+
1604+
org.docx4j.wml.Tc tc = factory.createTc();
1605+
if (sdtParent.equals("tr")) {
1606+
tc.getContent().add(p);
1607+
}
1608+
1609+
if (sdtParent.equals("body")
1610+
|| sdtParent.equals("tr")
1611+
|| sdtParent.equals("tc") ) {
1612+
p.getContent().add(run);
1613+
}
1614+
1615+
Document document = null;
1616+
1617+
if (sdtParent.equals("body")
1618+
|| sdtParent.equals("tc") ) {
1619+
document = XmlUtils.marshaltoW3CDomDocument(p);
1620+
log.debug(XmlUtils.marshaltoString(p, true, true));
1621+
} else if ( sdtParent.equals("tr") ) {
1622+
document = XmlUtils.marshaltoW3CDomDocument(tc);
1623+
log.debug(XmlUtils.marshaltoString(tc, true, true));
1624+
} else if ( sdtParent.equals("p") ) {
1625+
document = XmlUtils.marshaltoW3CDomDocument(run);
1626+
log.debug(XmlUtils.marshaltoString(run, true, true));
1627+
} else if ( sdtParent.equals("sdtContent") ) {
1628+
log.info("contentChild: " + contentChild);
1629+
if (contentChild.equals("p")) {
1630+
p.getContent().add(run);
1631+
document = XmlUtils.marshaltoW3CDomDocument(p);
1632+
log.debug(XmlUtils.marshaltoString(p, true, true));
1633+
} else if (contentChild.equals("r")) {
1634+
document = XmlUtils.marshaltoW3CDomDocument(run);
1635+
log.debug(XmlUtils.marshaltoString(run, true, true));
1636+
} else {
1637+
log.error("how to inject checkbox for unexpected sdt's content: " + contentChild);
1638+
}
1639+
} else {
1640+
log.error("how to inject checkbox for unexpected sdt's parent: " + sdtParent);
1641+
}
1642+
1643+
DocumentFragment docfrag = document.createDocumentFragment();
1644+
docfrag.appendChild(document.getDocumentElement());
1645+
1646+
return docfrag;
1647+
1648+
} catch (Exception e) {
1649+
e.printStackTrace();
1650+
return null;
1651+
}
1652+
}
1653+
15001654
// TODO - add something like this to RelationshipsPart??
15011655
private static PartName getNewPartName(String prefix, String suffix,
15021656
RelationshipsPart rp) throws InvalidFormatException {

src/main/java/org/docx4j/model/datastorage/bind.xslt

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11

22
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
3-
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
3+
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
4+
xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml"
5+
xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml"
6+
xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml"
47
xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
58
xmlns:o="urn:schemas-microsoft-com:office:office"
69
xmlns:v="urn:schemas-microsoft-com:vml"
@@ -175,6 +178,32 @@
175178

176179
</xsl:when>
177180

181+
<xsl:when test="w:sdtPr/w:dataBinding and w:sdtPr/w14:checkbox">
182+
<!-- since 3.2.2, honour w:dataBinding -->
183+
184+
<xsl:copy>
185+
<xsl:copy-of select="w:sdtPr"/>
186+
187+
<xsl:if test="w:stdEndPr">
188+
<xsl:copy-of select="w:sdtEndPr"/>
189+
</xsl:if>
190+
191+
<w:sdtContent>
192+
193+
<xsl:copy-of
194+
select="java:org.docx4j.model.datastorage.BindingTraverserXSLT.w14Checkbox(
195+
$wmlPackage,
196+
$sourcePart,
197+
$customXmlDataStorageParts,
198+
w:sdtPr,
199+
$parent,
200+
$child)" />
201+
</w:sdtContent>
202+
203+
</xsl:copy>
204+
205+
</xsl:when>
206+
178207
<xsl:when test="w:sdtPr/w:dataBinding and w:sdtPr/w:picture">
179208
<!-- honour w:dataBinding -->
180209

0 commit comments

Comments
 (0)