在 Eclipse 中从 XML 生成 Java 代码
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11904803/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Generating Java code from XML in Eclipse
提问by Kevin Lacquement
I am working on a project that will have several Java classes that are very similar to each other, and that I would like to generate from XML files. What I would like to be able to do is change the Eclipse build process to do something like this:
我正在开发一个项目,该项目将包含多个彼此非常相似的 Java 类,并且我想从 XML 文件生成这些类。我希望能够做的是更改 Eclipse 构建过程以执行以下操作:
- Compile the code generator
- Run the code generator, converting the XML to Java
- Compile the rest of the project
- 编译代码生成器
- 运行代码生成器,将 XML 转换为 Java
- 编译项目的其余部分
I could do this all manually but I would prefer to be able to have Eclipse do it all for me.
我可以手动完成这一切,但我更愿意让 Eclipse 为我完成这一切。
Example
例子
I want to be able to take a source XML file that looks like this:
我希望能够采用如下所示的源 XML 文件:
<command-list>
<command name="DATE" />
<command name="GROUP">
<capability "READER" />
<argument "groupname" />
</command>
<command name="ARTICLE">
<capability "READER" />
<argument "message-id" optional="true" />
</command>
</command-list>
and have it give me something similar to the following (in separate files as appropriate):
并让它给我类似于以下内容(在适当的单独文件中):
public class Date extends Command {
public ResponseCode execute() {
Server srv = getServer();
srv.send("DATE");
return srv.getResponse();
}
}
public class Group extends Command {
public ResponseCode execute() {
Server srv = getServer();
if (srv.hasCapability(Capabilities.READER) == false) {
Log.debug("Attempting non-available capability: READER");
}
String groupname = getArgument("groupname");
if (groupname == null) {
throw new InvalidArgumentException("Require groupname");
}
String command = "GROUP";
if (groupname != null) command += " " + groupname;
srv.send(command);
return srv.getResponse();
}
}
public class Article extends Command {
public ResponseCode execute() {
Server srv = getServer();
if (srv.hasCapability(Capabilities.READER) == false) {
Log.debug("Attempting non-available capability: READER");
}
String messageId = getArgument("messageId");
String command = "ARTICLE";
if (messageId != null) command += " " + messageId;
srv.send(command);
return srv.getResponse();
}
}
采纳答案by Chris Gerken
This is exactly what the JET component in the Model to Text (M2T) project was made for. In fact, you can even create the project, .classpath and any other files you need with JET.
这正是 Model to Text (M2T) 项目中的 JET 组件的用途。事实上,您甚至可以使用 JET 创建项目、.classpath 和任何其他文件。
Jet templates are as follows. Note that these templates must be named exactly as shown.
Jet 模板如下。请注意,这些模板的名称必须完全如图所示。
/templates/main.jet
/模板/main.jet
<%@taglib prefix="ws" id="org.eclipse.jet.workspaceTags" %>
<%-- Main entry point for com.lacqui.command.xform --%>
<%--
Let c:iterate tags set the XPath context object.
For 100% compatibility with JET 0.9.x or earlier, remove this statement
--%>
<c:setVariable var="org.eclipse.jet.taglib.control.iterateSetsContext" select="true()"/>
<c:setVariable select="/command-list" var="command-list" />
--- traverse input model, performing calculations and storing
--- the results as model annotations via c:set tag
<c:set select="$command-list" name="project">com.lacqui.commands</c:set>
<c:set select="$command-list" name="commandPkg">com.lacqui.commands</c:set>
<c:set select="$command-list" name="commandDir"><c:get select="translate($command-list/@commandPkg,'.','/')" /></c:set>
<c:iterate select="$command-list/command" var="command" >
- Derive the class name from the name of the command
<c:set select="$command" name="classname"><c:get select="camelCase($command/@name)" />Command</c:set>
<c:iterate select="$command/argument" var="argument">
<c:if test="not($argument/@optional)">
<c:set select="$argument" name="optional">false</c:set>
</c:if>
</c:iterate>
</c:iterate>
--- traverse annotated model, performing text generation actions
--- such as ws:file, ws:folder and ws:project
<ws:project name="{$command-list/@project}" />
<ws:file template="templates/project.jet" path="{$command-list/@project}/.project" />
<ws:file template="templates/classpath.jet" path="{$command-list/@project}/.classpath"/>
<c:iterate select="$command-list/command" var="command" >
<ws:file template="templates/class.jet" path="{$command-list/@project}/src/{$command-list/@commandDir}/{$command/@classname}.java" replace="true"/>
</c:iterate>
/templates/classpath.jet
/模板/classpath.jet
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="output" path="bin"/>
</classpath>
/templates/project.jet
/模板/project.jet
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name><c:get select="$command-list/@project" /></name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
/templates/class.jet
/模板/class.jet
package <c:get select="$command-list/@commandPkg" />;
public class <c:get select="$command/@classname" /> extends Command {
public ResponseCode execute() {
Server srv = getServer();
<c:iterate select="$command/capability" var="capability">
if (srv.hasCapability(Capabilities.<c:get select="$capability/@name"/>) == false) {
Log.debug("Attempting non-available capability: <c:get select="$capability/@name"/>");
}
</c:iterate>
<c:iterate select="$command/argument" var="argument">
String <c:get select="$argument/@name"/> = getArgument("<c:get select="$argument/@name"/>");
<c:if test="$argument/@optional = 'false'" >
if (<c:get select="$argument/@name"/> == null) {
throw new InvalidArgumentException("Require <c:get select="$argument/@name"/>");
}
</c:if>
</c:iterate>
String command = "GROUP";
<c:iterate select="$command/argument" var="argument">
if (<c:get select="$argument/@name"/> != null) command += " -<c:get select="$argument/@name"/> " + <c:get select="$argument/@name"/>;
</c:iterate>
srv.send(command);
return srv.getResponse();
}
}
and using this model:
并使用此模型:
<command-list>
<command name="DATE" />
<command name="GROUP">
<capability name="LOGGER" />
<capability name="AUTHENTICATOR" />
<argument name="groupname" />
</command>
<command name="ARTICLE">
<capability name="READER" />
<argument name="article-id" optional="false" />
<argument name="message-id" optional="true" />
</command>
</command-list>
gives a complete java project named com.lacqui.commands containing three java files:
给出了一个名为 com.lacqui.commands 的完整 java 项目,其中包含三个 java 文件:
package com.lacqui.commands;
public class ArticleCommand extends Command {
public ResponseCode execute() {
Server srv = getServer();
if (srv.hasCapability(Capabilities.READER) == false) {
Log.debug("Attempting non-available capability: READER");
}
String article-id = getArgument("article-id");
if (article-id == null) {
throw new InvalidArgumentException("Require article-id");
}
String message-id = getArgument("message-id");
String command = "GROUP";
if (article-id != null) command += " -article-id " + article-id;
if (message-id != null) command += " -message-id " + message-id;
srv.send(command);
return srv.getResponse();
}
}
and this:
和这个:
package com.lacqui.commands;
public class GroupCommand extends Command {
public ResponseCode execute() {
Server srv = getServer();
if (srv.hasCapability(Capabilities.LOGGER) == false) {
Log.debug("Attempting non-available capability: LOGGER");
}
if (srv.hasCapability(Capabilities.AUTHENTICATOR) == false) {
Log.debug("Attempting non-available capability: AUTHENTICATOR");
}
String groupname = getArgument("groupname");
if (groupname == null) {
throw new InvalidArgumentException("Require groupname");
}
String command = "GROUP";
if (groupname != null) command += " -groupname " + groupname;
srv.send(command);
return srv.getResponse();
}
}
回答by Dan
You might want to take a look at JaxB.
您可能想看看 JaxB。
Lars Vogel did a simple tutorial if you want to take a quick look at it.
JAXB Tutorial
如果您想快速浏览一下,Lars Vogel 做了一个简单的教程。
JAXB 教程
Also here is a benchmark test of xml unmarshaling.
XML unmarshalling benchmark in Java: JAXB vs STax vs Woodstox
这里还有一个 xml unmarshaling 的基准测试。
Java 中的 XML 解组基准测试:JAXB vs STax vs Woodstox