word文档模板 xml
本系列的第四部分也是最后一部分将向您展示如何使用模板创建文档,如何通过自己的方法实现来丰富投影以及如何扩展内置类型转换器。
我们已经在本系列的第二部分中演示了写作预测。 现在,我们将更深入地编写投影,并了解到XMLBeam不仅仅限于编写元素和属性的值。 利用第一部分中显示的子投影,可以将整个子图写入DOM树。 这可用于分别处理文档的静态和动态部分,从而减少编程工作。 因此,我们定义了作为投影读取的模板,并用Java代码进行了修改,然后组成了一个新文档。 我们提供了一个示例,简化了其说明原理的过程。
Example 1: Document template "svg_document_template.svg“
<svg>
<!-- simple document template -->
<g style="stroke:black; stroke-width:3;"/>
</svg>
元素“ <svg>”将成为我们文档的基础。 我们将在代码示例中插入更多元素,因此我们将创建更多具有合理默认值的模板。
Example 1: Element template "rect_template.svg“
<rect width="100" height="100" style="fill:blue" />
Example 1: Element template "circle_template.svg“
<circle r="50" style="fill:red" />
Example 1: Element template "ellipse_template.svg“
<ellipse rx="50" ry="100" style="fill:yellow" />
之后,我们定义投影界面以能够使用这些模板。 为了共享通用方法,投影 Rectangle , Circle 和 Ellipse 通过常规Java类型继承 从 Shape 继承投影方法 。 将投影定义为内部接口没有更深层的含义,这只是在我们的示例中节省了几行。
Example 1:
@XBDocURL("resource://svg_document_template.svg")
public interface SVG {
public interface Shape {
@XBWrite("./@x")
Shape setX(int x);
@XBWrite("./@y")
Shape setY(int y);
}
@XBDocURL("resource://rect_template.svg")
public interface Rect extends Shape {
@XBWrite("./@width")
Rect setWidth(int w);
@XBWrite("./@heigth")
Shape setHeight(int h);
}
@XBDocURL("resource://circle_template.svg")
public interface Circle extends Shape {
@XBWrite("./@r")
Shape setRadius(int r);
}
@XBDocURL("resource://ellipse_template.svg")
public interface Ellipse extends Shape {
@XBWrite("./@rx")
Shape setRadiusX(int rx);
@XBWrite("./@ry")
Shape setRadiusY(int ry);
}
@XBWrite("/svg/g/*")
SVG setShapes(List<Shape> shapes);
}
s etShapes(List <Shape> )方法是我们文档组成模式的关键。 它以 Shape 类型的投影 作为参数,并将这些投影作为元素“ <g>”的子元素插入到投影 SVG 的DOM树中 。 头是隐藏的,因为书写的对象不是元素的子投影,而是文档的投影。 XMLBeam支持此用例,并将根元素的副本插入DOM树。 之所以制作副本,是因为模板元素的所有权在写入操作期间发生了变化。 通配符“ *”指示XMLBeam保留写入的子元素的名称。 像“ / svn / g / shape”这样的XPath将导致将所有子元素重命名为“ shape”。
Example 1: Document composition with templates
XBProjector projector = new XBProjector(Flags.TO_STRING_RENDERS_XML);
Rect rect = projector.io().fromURLAnnotation(Rect.class);
Circle circle = projector.io().fromURLAnnotation(Circle.class);
Ellipse ellipse = projector.io().fromURLAnnotation(Ellipse.class);
List<Shape> shapes = new LinkedList<Shape>();
shapes.add(rect.setX(10).setY(120));
shapes.add(circle.setX(60).setY(60));
shapes.add(ellipse.setX(180).setY(120));
SVG svgDoc = projector.io().fromURLAnnotation(SVG.class);
svgDoc.setShapes(shapes);
System.out.println(svgDoc.toString());
作为示例的结果,我们获得了以下SVG文档。
Example 1: Result
<svg>
<!-- simple document template -->
<g style="stroke:black; stroke-width:3;">
<rect height="100" style="fill:blue" width="100" x="10" y="120"/>
<circle r="50" style="fill:red" x="60" y="60"/>
<ellipse rx="50" ry="100" style="fill:yellow" x="180" y="120"/>
</g>
</svg>
投影中的自定义方法实现
正如我们在本系列前面的部分中了解到的那样,可以像普通的旧Java对象(POJO)一样使用投影。 由于equals()和hashcode()的预定义实现,它们可以 直接 在 Collection中 使用 。 支持继承,并且通过扩展 Serializeable ,甚至可以像常规对象一样对投影进行序列化。 在这里,我们展示了如何向投影添加自己的方法实现。
如果XMLBeam与Java 8一起使用,则只需将自己的默认方法添加到投影接口即可。 XMLBeam与Java 6兼容,但仍将检测默认方法调用并将其转发给Java 8实现。 如果您使用Java 8之前的版本并且不能使用默认方法,那么仍然可以使用一种方法来覆盖方法或添加自己的实现。
为此,XMLBeam利用与其他编程语言中的mixin相似的概念。 XMLBeam当然不会使用真正的mixin扩展Java语言的功能,但是该术语是适合此上下文的隐喻。 从现在开始,它将用于一堆要添加到投影中的方法。 它是这样工作的:首先定义一个mixin接口:
A "mixin-interface“
public interface Validatable {
boolean isValid();
}
我们让投影接口从mixin接口 Validatable 继承, 以便 isValid() 方法 可用于投影接口的客户端。
A projection with inherited method "isValid()“
public interface Person extends Validatable {
@XBRead("/person/@age“)
int getAge();
}
mixin方法的定义仍然缺失。 它是在单独的“混合对象”中实现的,在创建投影之前,投影机必须将其注册:
Registering a mixin implementation
projektor.mixins().addProjectionMixin(Person.class,new Validatable() {
private Person me;
@Override
public boolean isValid() {
return me.getAge() >= 18;
}
});
XMLBeam将对person.isValid()的调用委托给为相应的投影接口 Person 注册的mixin对象 。 为了使该投影对于混合实现变得可见,投影仪将当前投影预先注入到属性“ me”中。 可以为不同的投影接口注册不同的mixin实现。 甚至有可能重写现有的方法,例如“ toString()”(请参阅[2],或使用现有的接口,例如 Comparable 作为mixin接口(请参见[3])。
创建一个类型转换器
XMLBeam注意读取的XML数据会自动转换为所需的投影方法返回类型。 这些转换可以轻松扩展以满足您的要求。
A custom type converter
public static class HexToLongConversion extends Conversion<Long> {
private HexToLongConversion(final Long defaultValue) {
super(defaultValue);
}
@Override
public Long convert(final String data) {
return Long.parseLong(data, 16);
}
}
public interface Projection {
@XBRead("/foo")
long getData();
}
在我们的示例中,XML字符串中的十六进制数字应转换为 Long 值。 为了对此进行归档,我们实现了 Conversion 接口, 并将我们的实例作为 Long的 所需转换移交给DefaultTypeConverter 。
Using the type converter
XBProjector projector = new XBProjector();
DefaultTypeConverter converter = projector.config().getTypeConverterAs(DefaultTypeConverter.class);
converter.setConversionForType(Long.TYPE, new HexToLongConversion(0L));
Projection projection = projector.projectXMLString("<foo>CAFEBABE</foo>", Projection.class);
assertEquals(3405691582L, projection.getData());
这是覆盖现有转化所要做的全部工作。 以相同的方式添加了针对自己的Java类型的新转换。 如果您已经具有可以用 String 实例化的值类,则 有一个捷径:XMLBeam自动调用 投影方法返回类型的 String 构造函数或 String -Factory方法(请参见[4])。
这样就完成了有关XMLBeam的系列文章。 在项目站点[1]有更多的教程和示例有待探索。
关于作者
Sven Ewald(Twitter句柄:@Cfx)是库XMLBeam(@XMLBeam)的作者。 他从事Java解决方案已有15年的历史了,而且还没有结束。 目前,他在汽车行业的领域特定语言领域工作。
Links & Literature
[2] http://xmlbeam.org/faq.html#How_do_I_implement_the_toString_method_for_my_projection
[3] http://xmlbeam.org/t07.html
word文档模板 xml