Thymeleaf 元素模型处理
Thymeleaf Element Model processing
如何在我自己的元素模型处理器中正确处理 HTML 标记及其主体?例如,我有以下 HTML 结构:
<my:form id="some_id">
<my:input type="text" name="input-1"/>
<my:input type="number" name="input-2"/>
</my:form>
我想通过添加一些生成的属性来更改包装 my:form
标记,以便输出看起来像 <form id="some_id" other-attr="_generated_value_">...</form>
并通过添加一个来处理每个内部 my:input
每个输入都带有表单 ID 的属性(并且通常按应有的方式处理这些标签),例如<input type="text" name="input-1" id="generated_1" form-id="some_id">
。通常 my:input
由我的 AbstractAttributeTagProcessor
分机处理。
截至目前,我已经扩展 AbstractElementModelProcessor
创建处理器,如下所示:
public class MyFormProcessor extends AbstractElementModelProcessor {
private static final String ELEMENT_NAME = "form";
private static final int PRECEDENCE = 1000;
public MyFormProcessor( final String dialectPrefix ) {
super(
TemplateMode.HTML,
dialectPrefix, // dialect prefix - 'my' in this case
ELEMENT_NAME,
true, // filter by element name prefix
null,
false,
PRECEDENCE
);
}
@Override
protected void doProcess( ITemplateContext context,
IModel model,
IElementModelStructureHandler structureHandler ) {
// what goes here?
}
}
处理器已正确注册并将表单及其正文转换为一系列事件,但我还没有弄清楚如何正确修改 model
,因为我找不到任何修改方法它的元素。
提前感谢您的指导!
为了使您的示例正常工作,我需要更改您的自定义 Thymeleaf 输入结构:
<my:form id="some_id">
<my:input type="text" name="input-1">
<my:input type="number" name="input-2">
</my:form>
不同之处在于我不会自行关闭 <my:input>
标签(它们以 >
而不是 />
结尾。这是为了反映目标的结构“独立”<input>
元素,也不是自闭合的。
我的方法处理输入的整个片段 HTML - 因此,如果您也已经有一个用于 <my:input>
标签的单独处理器,那么我认为这需要比那个更高的优先级.
这里是doProcess()
方法,代码中有注释:
@Override
protected void doProcess(ITemplateContext context,
IModel model,
IElementModelStructureHandler structureHandler) {
final IModelFactory modelFactory = context.getModelFactory();
// first handle the form element:
String formID = null;
final ITemplateEvent formEvent = model.get(0);
if (formEvent instanceof IOpenElementTag) {
// retrieve the form's ID value:
IOpenElementTag ele = (IOpenElementTag) formEvent;
IAttribute attr = ele.getAttribute("id");
formID = attr.getValue();
}
// build the attributes we want the form element to use:
Map<String, String> formAttrs = new HashMap<>();
formAttrs.put("id", formID);
formAttrs.put("other-attr", "_generated_value_");
// create the form element:
IOpenElementTag formOpen = modelFactory
.createOpenElementTag("form", formAttrs,
AttributeValueQuotes.DOUBLE,
false);
model.replace(0, formOpen);
int idInt = 1; // used to increment ID values
// the loop processes all of the elements inside the form's opening
// and closing tags:
for (int i = 1; i < model.size() - 1; i++) {
final ITemplateEvent inputEvent = model.get(i);
if (inputEvent instanceof IOpenElementTag) {
IOpenElementTag ele = (IOpenElementTag) inputEvent;
// we will add some more attributes here:
Map<String, String> attrs = ele.getAttributeMap();
attrs.put("form-id", formID);
attrs.put("id", "generated_" + idInt++); // the "idInt++" is just a demo - use whatever sequence you want here
IOpenElementTag openEle = modelFactory
.createOpenElementTag("input", attrs,
AttributeValueQuotes.DOUBLE,
false);
model.replace(i, openEle);
}
}
}
最终结果HTML如下:
<form other-attr="_generated_value_" id="some_id">
<input type="text" name="input-1" form-id="some_id" id="generated_1">
<input type="number" name="input-2" form-id="some_id" id="generated_2">
</form>
备注
您可以做更多的事情来重构代码。
对于这里显示的方法,可能有替代(也许更好)的方法。使用 Thymeleaf,做某事的方法通常不止一种。
如何在我自己的元素模型处理器中正确处理 HTML 标记及其主体?例如,我有以下 HTML 结构:
<my:form id="some_id">
<my:input type="text" name="input-1"/>
<my:input type="number" name="input-2"/>
</my:form>
我想通过添加一些生成的属性来更改包装 my:form
标记,以便输出看起来像 <form id="some_id" other-attr="_generated_value_">...</form>
并通过添加一个来处理每个内部 my:input
每个输入都带有表单 ID 的属性(并且通常按应有的方式处理这些标签),例如<input type="text" name="input-1" id="generated_1" form-id="some_id">
。通常 my:input
由我的 AbstractAttributeTagProcessor
分机处理。
截至目前,我已经扩展 AbstractElementModelProcessor
创建处理器,如下所示:
public class MyFormProcessor extends AbstractElementModelProcessor {
private static final String ELEMENT_NAME = "form";
private static final int PRECEDENCE = 1000;
public MyFormProcessor( final String dialectPrefix ) {
super(
TemplateMode.HTML,
dialectPrefix, // dialect prefix - 'my' in this case
ELEMENT_NAME,
true, // filter by element name prefix
null,
false,
PRECEDENCE
);
}
@Override
protected void doProcess( ITemplateContext context,
IModel model,
IElementModelStructureHandler structureHandler ) {
// what goes here?
}
}
处理器已正确注册并将表单及其正文转换为一系列事件,但我还没有弄清楚如何正确修改 model
,因为我找不到任何修改方法它的元素。
提前感谢您的指导!
为了使您的示例正常工作,我需要更改您的自定义 Thymeleaf 输入结构:
<my:form id="some_id">
<my:input type="text" name="input-1">
<my:input type="number" name="input-2">
</my:form>
不同之处在于我不会自行关闭 <my:input>
标签(它们以 >
而不是 />
结尾。这是为了反映目标的结构“独立”<input>
元素,也不是自闭合的。
我的方法处理输入的整个片段 HTML - 因此,如果您也已经有一个用于 <my:input>
标签的单独处理器,那么我认为这需要比那个更高的优先级.
这里是doProcess()
方法,代码中有注释:
@Override
protected void doProcess(ITemplateContext context,
IModel model,
IElementModelStructureHandler structureHandler) {
final IModelFactory modelFactory = context.getModelFactory();
// first handle the form element:
String formID = null;
final ITemplateEvent formEvent = model.get(0);
if (formEvent instanceof IOpenElementTag) {
// retrieve the form's ID value:
IOpenElementTag ele = (IOpenElementTag) formEvent;
IAttribute attr = ele.getAttribute("id");
formID = attr.getValue();
}
// build the attributes we want the form element to use:
Map<String, String> formAttrs = new HashMap<>();
formAttrs.put("id", formID);
formAttrs.put("other-attr", "_generated_value_");
// create the form element:
IOpenElementTag formOpen = modelFactory
.createOpenElementTag("form", formAttrs,
AttributeValueQuotes.DOUBLE,
false);
model.replace(0, formOpen);
int idInt = 1; // used to increment ID values
// the loop processes all of the elements inside the form's opening
// and closing tags:
for (int i = 1; i < model.size() - 1; i++) {
final ITemplateEvent inputEvent = model.get(i);
if (inputEvent instanceof IOpenElementTag) {
IOpenElementTag ele = (IOpenElementTag) inputEvent;
// we will add some more attributes here:
Map<String, String> attrs = ele.getAttributeMap();
attrs.put("form-id", formID);
attrs.put("id", "generated_" + idInt++); // the "idInt++" is just a demo - use whatever sequence you want here
IOpenElementTag openEle = modelFactory
.createOpenElementTag("input", attrs,
AttributeValueQuotes.DOUBLE,
false);
model.replace(i, openEle);
}
}
}
最终结果HTML如下:
<form other-attr="_generated_value_" id="some_id">
<input type="text" name="input-1" form-id="some_id" id="generated_1">
<input type="number" name="input-2" form-id="some_id" id="generated_2">
</form>
备注
您可以做更多的事情来重构代码。
对于这里显示的方法,可能有替代(也许更好)的方法。使用 Thymeleaf,做某事的方法通常不止一种。