问题
I recently wrote a custom dialect for thymeleaf 3.0.7 with a tag processor to merge a fragment with the custom tag's body.
For example I have a fragment like this
<!-- file fragments/myfrag.html -->
<div th:fragment="content(header)">
<h1 th:text="${header}">Header 1</h1>
<my:content/>
<span>Some span</span>
</div>
And a custom tag like
<my:merger my:mergefragment="fragments/myfrag :: content('Hello world')">
<h2>Header 2</h2>
<button>Test</button>
</my:merger>
The result should be like
<div>
<h1>Hello world</h1>
<h2>Header 2</h2> <!-- Content of my:merger -->
<button>Test</button> <!-- Content of my:merger -->
<span>Some span</span>
</div>
My question is how to get the body of my custom tag <my:merger>
? Currently I have the following processor.
public class MergerElementTagProcessor extends AbstractElementTagProcessor {
private static final String TAG_NAME = "merger";
public MergerElementTagProcessor(final String dialectPrefix) {
super(TemplateMode.HTML, dialectPrefix, TAG_NAME, true, null, false, 1000);
}
@Override
protected void doProcess(ITemplateContext context, IProcessableElementTag tag, IElementTagStructureHandler structureHandler) {
final IEngineConfiguration configuration = context.getConfiguration();
final Fragment fragment = (Fragment) computeFragment(context, tag.getAttributeValue("mergefragment"));
final Writer stringWriter = new FastStringWriter(200);
configuration.getTemplateManager().process(fragment.getTemplateModel(), context, stringWriter);
String elementBody = getBody(tag); // how do I get the body of my <my:merger></<my:merger> tag at his point?
structureHandler.replaceWith(merge(stringWriter.toString(), elementBody), false);
}
private String merge(String fragment, String elementBody) {
return fragment.replace("<my:content/>", elementBody);
}
}
Thanks in advice for any help or tips.
回答1:
As an answer of Metroids hint I got it done with the following code:
public class MergerElementTagProcessor extends AbstractElementModelProcessor {
private static final String TAG_NAME = "merger";
public MergerElementTagProcessor(final String dialectPrefix) {
super(TemplateMode.HTML, dialectPrefix, TAG_NAME, true, null, false, 1000);
}
@Override
protected void doProcess(ITemplateContext context, IModel model,
IElementModelStructureHandler structureHandler) {
IProcessableElementTag tag = processElementTag(context, model); // convert IModel to IProcessableElementTag
Map<String, String> attrMap = processAttribute(context, tag); // get attributes of tag
IModel baseModelClone = model.cloneModel(); // clone base model
IModel fragmentModel = (IModel) computeFragment(context, tag.getAttributeValue("mergefragment")); // get fragment as IModel
model.reset(); // clear the model reference
model.addModel(mergeModel(fragmentModel, baseModelClone, "<my:content/>")); // merge the two IModels
}
protected IModel mergeModel(IModel fragment, IModel body, final String replaceTag) {
IModel mergedModel = insert(fragment, body, replaceTag);
mergedModel = remove(mergedModel, replaceTag);
mergedModel = remove(mergedModel, replaceTag);
return mergedModel;
}
private IModel insert(IModel fragment, IModel body, final String replaceTag) {
IModel mergedModel = fragment.cloneModel();
int size = mergedModel.size();
ITemplateEvent event = null;
for (int i = 0; i < size; i++) {
event = mergedModel.get(i);
if (event instanceof IOpenElementTag) {
if (event.toString().contains(replaceTag)) {
mergedModel.insertModel(i, body);
break;
}
}
}
return mergedModel;
}
private IModel remove(IModel fragment, final String replaceTag) {
IModel mergedModel = fragment.cloneModel();
int size = mergedModel.size();
ITemplateEvent event = null;
for (int i = 0; i < size; i++) {
event = mergedModel.get(i);
if (event instanceof IOpenElementTag || event instanceof ICloseElementTag) {
if (event.toString().contains(replaceTag)) {
mergedModel.remove(i);
break;
}
}
}
return mergedModel;
}
}
来源:https://stackoverflow.com/questions/46074574/how-to-get-body-of-tag-in-processor-for-a-custom-dialect-in-thymeleaf-3-0-x