Error generating document: Bad Request is not the best message. Sometimes it means you have a custom template content that’s blowing up. One of the reasons this might be happening is that you are trying to output the description field for each line. Well, that’s a bummer because the VF page for the custom content has to be in XSL:FO, not HTML. But rich text fields are stored in HTML. SO! How do you get your rich text field to display in a custom content?? Two ways: either strip all HTML tags out of your rich text field’s value -OR- use the code below to translate your rich text HTML tags to XSL:FO! Yep. This translates most tags. Leave a comment with any tags that aren’t translating!
public String htmlToFo(String html){
String output = '';
if (html != null) {
System.debug('html: '+html);
DOM.Document doc = new DOM.Document();
Dom.Document newdoc = new DOM.Document();
doc.load('<block>'+html.replace('<br>', '<br />').replace('&', '&')+'</block>');
Dom.XMLNode root = doc.getRootElement();
Dom.XMLNode newroot = newdoc.createRootElement('block', null, null);
newroot = convertNodes(root.getChildren(), newroot, 0, '');
output = newdoc.toXmlString().replace('<?xml version="1.0" encoding="UTF-8"?>', '');
System.debug('output: '+output);
}
return output;
}
private Map<Decimal, String> listBulletsByLevel = new Map<Decimal, String>{
0 => '•',
1 => 'â—¦',
2 => '▪︎'
};
private Dom.XMLNode convertNodes(List<Dom.XMLNode> childrenToConvert, Dom.XMLNode newroot, Decimal listlevel, String listtype) {
if (newroot != null) {
Decimal orderedListCurrentItem = 1;
for(Dom.XMLNode child : childrenToConvert) {
Dom.XMLNode newchild = null;
if (child.getName() == 'br') {
newchild = newroot.addChildElement('block', null, null);
newchild.setAttribute('padding-top', '0pt');
newchild.setAttribute('padding-bottom', '0pt');
newchild.addTextNode(' ');
} else if (child.getName() == 'p') {
newchild = newroot.addChildElement('block', null, null);
newchild.setAttribute('padding-top', '10pt');
newchild.setAttribute('padding-bottom', '4pt');
} else if (child.getName() == 'div') {
newchild = newroot.addChildElement('block', null, null);
newchild.setAttribute('padding-top', '0pt');
newchild.setAttribute('padding-bottom', '0pt');
} else if (child.getName() == 'ul') {
listtype='unordered';
newchild = newroot.addChildElement('list-block', null, null);
newchild.setAttribute('padding-top', '4pt');
} else if (child.getName() == 'ol') {
orderedListCurrentItem = 1;
listtype='ordered';
newchild = newroot.addChildElement('list-block', null, null);
newchild.setAttribute('padding-top', '4pt');
} else if (child.getName() == 'li') {
newchild = newroot.addChildElement('list-item', null, null);
Dom.XMLNode label = newchild.addChildElement('list-item-label', null, null);
Decimal indent = listtype == 'unordered' ? 19 : 24;
label.setAttribute('start-indent', (13+(listlevel*13))+'pt');
if (listtype == 'unordered') {
label.addChildElement('block', null, null).addTextNode((String)(listBulletsByLevel.get(0)));//listlevel>2?0:listlevel)));
} else {
label.addChildElement('block', null, null).addTextNode(orderedListCurrentItem+'.');
}
Dom.XMLNode body = newchild.addChildElement('list-item-body', null, null);
body.setAttribute('start-indent', (indent+(listlevel*13))+'pt');
Dom.XMLNode bodytext = body.addChildElement('block', null, null);
newchild = bodytext;
listlevel++;
orderedListCurrentItem++;
} else if (child.getName() == 'strong') {
newchild = newroot.addChildElement('inline', null, null);
newchild.setAttribute('font-weight', 'bold');
} else if (child.getName() == 'em' || child.getName() == 'i') {
newchild = newroot.addChildElement('inline', null, null);
newchild.setAttribute('font-style', 'italic');
} else if (child.getName() == 'u') {
newchild = newroot.addChildElement('inline', null, null);
newchild.setAttribute('text-decoration', 'underline');
} else if (child.getName() == 's') {
newchild = newroot.addChildElement('inline', null, null);
newchild.setAttribute('text-decoration', 'line-through');
} else if (child.getName() == 'sub') {
newchild = newroot.addChildElement('inline', null, null);
newchild.setAttribute('vertical-align', 'sub');
newchild.setAttribute('font-size', '8pt');
} else if (child.getName() == 'sup') {
newchild = newroot.addChildElement('inline', null, null);
newchild.setAttribute('vertical-align', 'sup');
newchild.setAttribute('font-size', '8pt');
} else if (child.getName() == 'blockquote') {
newchild = newroot.addChildElement('block', null, null);
newchild.setAttribute('start-indent', '13pt');
} else if (child.getName() == 'img') {
newchild = newroot.addChildElement('external-graphic', null, null);
if (child.getAttributeValue('width', null) != null && child.getAttributeValue('width', null) != '') {
newchild.setAttribute('content-width', child.getAttributeValue('width', null));
}
if (child.getAttributeValue('height', null) != null && child.getAttributeValue('height', null) != '') {
newchild.setAttribute('content-height', child.getAttributeValue('height', null));
}
newchild.setAttribute('src', child.getAttributeValue('src', null));
} else if (child.getName() == 'a') {
newchild = newroot.addChildElement('basic-link', null, null);
newchild.setAttribute('color', 'blue');
newchild.setAttribute('text-decoration', 'underline');
newchild.setAttribute('external-destination', child.getAttributeValue('href', null));
} else {
newchild = newroot.addChildElement('inline', null, null);
newchild.addTextNode(child.getText());
}
if (child.getAttributeValue('style', null) != null && child.getAttributeValue('style', null) != '') {
String style = child.getAttributeValue('style', null);
if (style.contains('background-color')) {
Pattern pat = Pattern.compile('.*?background-color:\\s*([^;]+).*?');
Matcher match = pat.matcher(style);
match.find();
Integer groupsToCapture = match.groupCount();
if (groupsToCapture > 0) {
String bgcolor = match.group(1).replace(';', '');
newchild.setAttribute('background-color', bgcolor);
}
style = style.replace('background-color', '');
}
if (style.contains('color')) {
Pattern pat = Pattern.compile('.*?color:\\s*([^;]+).*?');
Matcher match = pat.matcher(style);
match.find();
Integer groupsToCapture = match.groupCount();
if (groupsToCapture > 0) {
String color = match.group(1).replace(';', '');
newchild.setAttribute('color', color);
}
}
if (style.contains('font-size')) {
Pattern pat = Pattern.compile('.*?font-size:\\s*([^;]+).*?');
Matcher match = pat.matcher(style);
match.find();
Integer groupsToCapture = match.groupCount();
if (groupsToCapture > 0) {
String fontSize = match.group(1).replace(';', '');
newchild.setAttribute('font-size', fontSize);
}
}
}
// process any child elements of this element.
List<Dom.XMLNode> grandkids = child.getChildren();
if (grandkids != null && grandkids.size() > 0) {
convertNodes(grandkids, newchild, listlevel, listtype);
}
if (child.getName() == 'li') {
listlevel--;
}
}
}
return newroot;
}
Comments