代码生成 - XML 到 Java

发布于 2024-10-17 15:33:00 字数 1999 浏览 3 评论 0 原文

我正在寻找一种从 XML 动态生成(意味着每次其他 java 类)Java 类的方法。初始 XML 基于 XSD,但结果类应为 bean。 示例:

XSD(很快):

Configuration->configuration-item->name
                                  ->value
                                  ->type
                                  ->scope
              ->impl-class-info

基本上是一个简单的参数,带有实现类名称和配置项 XML 列表

(示例):

<configuration>
 <impl-class-info>desired.class.name.APPConfig</impl-class-info>
 <configuration-item>
   <name>ipOfSomeServer</name>
   <type>string</type>
   <value>8.8.8.8</value>
   <scope></scope>
 </configuration-item>

 <configuration-item>
   <name>portOfSomeServer</name>
   <type>string</type>
   <value>1099</value>
   <scope></scope>
 </configuration-item>
</configuration>

生成的 java 类应如下所示:

package desired.class.name;

import xxx.xxx.xxx.ConfigurationElement;

public class APPConfig extends ConfigurationElement {

private String ipOfSomeServer;
private String portOfSomeServer;

public void setIpOfSomeServer(String ipOfSomeServer){
   this.ipOfSomeServer = ipOfSomeServer;
}
public void setPortOfSomeServer(String portOfSomeServer){
   this.portOfSomeServer = portOfSomeServer;
}

public String getPortOfSomeServer(){
   return this.portOfSomeServer;
}

public String getIpOfSomeServer(){
   return this.ipOfSomeServer;
}

如何做到这一点?我迷路了。我查看了(也许不够好)JAXB、XStream、XMLBeans,但它似乎不是我需要的。

“复杂的输入 XML”可以通过 XSLT(我认为)转换为简单的 XML,

<desired.class.name.APPConfig>
 <ipOfSomeServer>8.8.8.8</ipOfSomeServer>
 <portOfSomeServer>1099</portOfSomeServer>
</desired.class.name.APPConfig>

但是那又怎样呢?

提前致谢 亚历克斯

·P.S.在尝试了一些技术之后,我接受了使用 XSLT 将 XML 转换为文本(语法上的 Java 类)的挑战。之前使用 maven 进行的 XML 验证并定义了 XSD。
感谢大家的帮助。

I'm looking for a way to generate dynamically (means, every time other java class) Java class from XML. The initial XML based on a XSD, but the result class shall be a bean.
Example:

XSD (just shortly):

Configuration->configuration-item->name
                                  ->value
                                  ->type
                                  ->scope
              ->impl-class-info

Basically one simple param with a implementation class name and list of configuration-item

XML (example):

<configuration>
 <impl-class-info>desired.class.name.APPConfig</impl-class-info>
 <configuration-item>
   <name>ipOfSomeServer</name>
   <type>string</type>
   <value>8.8.8.8</value>
   <scope></scope>
 </configuration-item>

 <configuration-item>
   <name>portOfSomeServer</name>
   <type>string</type>
   <value>1099</value>
   <scope></scope>
 </configuration-item>
</configuration>

The generated java class shall be like that:

package desired.class.name;

import xxx.xxx.xxx.ConfigurationElement;

public class APPConfig extends ConfigurationElement {

private String ipOfSomeServer;
private String portOfSomeServer;

public void setIpOfSomeServer(String ipOfSomeServer){
   this.ipOfSomeServer = ipOfSomeServer;
}
public void setPortOfSomeServer(String portOfSomeServer){
   this.portOfSomeServer = portOfSomeServer;
}

public String getPortOfSomeServer(){
   return this.portOfSomeServer;
}

public String getIpOfSomeServer(){
   return this.ipOfSomeServer;
}

How can it be done? I'm getting lost. I looked (maybe not good enough) on JAXB,XStream, XMLBeans but it doesn't seems what I need.

The "complex input XML" maybe converted by XSLT (I think) to a simple one

<desired.class.name.APPConfig>
 <ipOfSomeServer>8.8.8.8</ipOfSomeServer>
 <portOfSomeServer>1099</portOfSomeServer>
</desired.class.name.APPConfig>

But what than?

Thanks in advance
Alex

P.S. After trying a few techniques I took a challenge to use XSLT to convert XML to Text (which syntactically Java class). The XML validation made previously using maven and defined XSD.
Thanks to all for the help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

红衣飘飘貌似仙 2024-10-24 15:33:00

您可以首先解析 XML(使用许多可用的解析器之一,例如 XPath)并相应地生成代码。

您可以使用一个非常好的 Java 代码解析器/生成器,名为 Javaparser 。这个名称有点误导,因为它可用于从头开始创建新的编译单元。

一个例子:

 /**
     * creates the compilation unit
     */
    private static CompilationUnit createCU() {
        CompilationUnit cu = new CompilationUnit();
        // set the package
        cu.setPakage(new PackageDeclaration(ASTHelper.createNameExpr("java.parser.test")));

        // create the type declaration 
        ClassOrInterfaceDeclaration type = new ClassOrInterfaceDeclaration(ModifierSet.PUBLIC, false, "GeneratedClass");
        ASTHelper.addTypeDeclaration(cu, type);

        // create a method
        MethodDeclaration method = new MethodDeclaration(ModifierSet.PUBLIC, ASTHelper.VOID_TYPE, "main");
        method.setModifiers(ModifierSet.addModifier(method.getModifiers(), ModifierSet.STATIC));
        ASTHelper.addMember(type, method);

        // add a parameter to the method
        Parameter param = ASTHelper.createParameter(ASTHelper.createReferenceType("String", 0), "args");
        param.setVarArgs(true);
        ASTHelper.addParameter(method, param);

        // add a body to the method
        BlockStmt block = new BlockStmt();
        method.setBody(block);

        // add a statement do the method body
        NameExpr clazz = new NameExpr("System");
        FieldAccessExpr field = new FieldAccessExpr(clazz, "out");
        MethodCallExpr call = new MethodCallExpr(field, "println");
        ASTHelper.addArgument(call, new StringLiteralExpr("Hello World!"));
        ASTHelper.addStmt(block, call);

        return cu;
    }

You can start by parsing the XML (using one of the many available parsers, say XPath) and generate the code accordingly.

There is a very nice Java code parser/generator that you can use, named Javaparser. The name is a bit misleading because it can also be used to create new compilation units from scratch.

An example:

 /**
     * creates the compilation unit
     */
    private static CompilationUnit createCU() {
        CompilationUnit cu = new CompilationUnit();
        // set the package
        cu.setPakage(new PackageDeclaration(ASTHelper.createNameExpr("java.parser.test")));

        // create the type declaration 
        ClassOrInterfaceDeclaration type = new ClassOrInterfaceDeclaration(ModifierSet.PUBLIC, false, "GeneratedClass");
        ASTHelper.addTypeDeclaration(cu, type);

        // create a method
        MethodDeclaration method = new MethodDeclaration(ModifierSet.PUBLIC, ASTHelper.VOID_TYPE, "main");
        method.setModifiers(ModifierSet.addModifier(method.getModifiers(), ModifierSet.STATIC));
        ASTHelper.addMember(type, method);

        // add a parameter to the method
        Parameter param = ASTHelper.createParameter(ASTHelper.createReferenceType("String", 0), "args");
        param.setVarArgs(true);
        ASTHelper.addParameter(method, param);

        // add a body to the method
        BlockStmt block = new BlockStmt();
        method.setBody(block);

        // add a statement do the method body
        NameExpr clazz = new NameExpr("System");
        FieldAccessExpr field = new FieldAccessExpr(clazz, "out");
        MethodCallExpr call = new MethodCallExpr(field, "println");
        ASTHelper.addArgument(call, new StringLiteralExpr("Hello World!"));
        ASTHelper.addStmt(block, call);

        return cu;
    }
行至春深 2024-10-24 15:33:00

当我过去编写代码生成器时,我所做的首先是创建一个中间步骤 - 一个针对我想要生成代码的事物的模型。然后您有两个步骤:

  1. 使用您最喜欢的 XML 解析库将 XML 解析到模型中
  2. 使用模板引擎(Velocity 是我的最爱)从模型生成代码。

这很好,因为它更容易测试,并且如果您决定将 XML 更改为更易于阅读的 DSL,则更改会容易得多。

When I've written code generators in the past, what I've done is first created an intermediate step - a model for the kinds of things I wanted to generate code around. You then have two steps:

  1. Parse XML using your favorite XML parsing library into the model
  2. Use a templating engine (Velocity is my favority) for generating code from the model.

This is nice because it is easier to test, and if you decide to change out the XML for a DSL which is easier to read, the change is much easier.

诗酒趁年少 2024-10-24 15:33:00

您误解了 XSLT 在这种情况下的作用。

XSLT 可用于将一个 XML 文档转换为另一个 XML 文档,也可用于将一个 XML 文档转换为另一个非 XML 文档。您想要创建一个 XSLT,将“源 XML”转换为 java 代码。

以下是将 XML 转换为 CSV 的 XSL 转换示例。希望它能让您深入了解如何将 XML 转换为非 XML 输出。

顺便说一句,您很快就会发现 XML 对于大多数编程语言来说都是一个糟糕的包装。

You misunderstand the role of XSLT in this situation.

XSLT can be used to translate one XML document into another XML document, or it can be used to translate one XML document into another non-XML document. You want to create an XSLT which translates your "source XML" into java code.

Here is an example of an XSL transform which converts XML to CSV. Hopefully it will give you the insight to see how XML can be transformed to non-XML output.

As an aside, you will quickly find out that XML makes a poor wrapper for most programming languages.

无名指的心愿 2024-10-24 15:33:00

我不知道有什么神奇的工具可以做到这一点,但是如果您准备好实际编写一些代码,那么我认为您可以:

  • 敲一些东西来解析 XML(使用内置的 XPath/DOM API)并吐出相应的Java源代码
  • 使用 Java Compiler API 来编译它

I don't know of a magic tool to do this, but if you're prepared to Actually Write Some Code, then I think you could:

  • knock something up to parse the XML (fairly easy with e.g. built-in XPath/DOM API) and spit out corresponding Java source code
  • use the Java Compiler API to compile it
天荒地未老 2024-10-24 15:33:00

我相信 JiBX 套件 中的一个工具可以完成这项工作。我想没有人想让它们在运行时使用,可能只使用一次,但我仍然没有看到任何可以阻止您将其嵌入到运行时代码中的东西。

顺便说一句,我不太明白为什么你想要在运行时生成一个类。如果您在运行时生成一个类,它与普通的 Map 属性映射有何不同(或者相比之下它带来什么值)?

I believe one of the tools from the JiBX suite would do the job. I guess no-one have meant them to be used at runtime, probably once only, but still I don't see anything that would stop you from embedding it into your runtime code.

BTW, I don't quite follow why do you want a class to be generated at runtime. If you generate a class at runtime how is it different (or what value it brings when compared to) than plain Map<String,Object> property map?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文