简体   繁体   English

如何使用commons-digester将XML文件表示为Java对象?

[英]How do I represent an XML file as a Java object using commons-digester?

Following on from my recent question regarding parsing XML files in Java I have decided to use the commons-digester library. 在我最近有关在Java中解析XML文件的问题之后,我决定使用commons-digester库。 I am now familiar with this process and now want to create a Java class representing the XML file, so that when a user instantiates a new object of that class, all of the data from the XML file will be available. 我现在熟悉此过程,现在想创建一个表示XML文件的Java类,以便当用户实例化该类的新对象时,XML文件中的所有数据将可用。

To illustrate this I have an XML file, called MyConfig.xml, with the following structure: 为了说明这一点,我有一个名为MyConfig.xml的XML文件,其结构如下:

<MyConfig>
    <ServerName>nile</ServerName>
    <ServerPort>8079</ServerPort>
</MyConfig>

I also have a Java class, called MyConfig.java, that represents this XML file. 我还有一个Java类,称为MyConfig.java,它代表此XML文件。 It has a constructor which takes in the location of the XML file and will then parse and output the contents of the XML file. 它具有一个构造器,该构造器接收XML文件的位置,然后将解析并输出XML文件的内容。 The class is of the following structure: 该类具有以下结构:

package com.digestersample;

import java.io.File;
import java.io.IOException;

import org.apache.commons.digester.Digester;
import org.xml.sax.SAXException;

public class MyConfig {
    private String serverName;
    private String serverPort;

    public MyConfig(String configFile) throws IOException, SAXException
    {
        Digester digester = new Digester();
        digester.setValidating(false);

        digester.addObjectCreate("MyConfig", MyConfig.class);

        digester.addCallMethod("MyConfig/ServerName", "setServerName", 0);
        digester.addCallMethod("MyConfig/ServerPort", "setServerPort", 0);

        System.out.println("Creating MyConfig...");
        MyConfig mc = (MyConfig) digester.parse(new File(configFile));
        System.out.println("Done.");

        System.out.println("Port: " + mc.getServerName());
        System.out.println("Port: " + mc.getServerPort());
    }

    public String getServerName() {
        return serverName;
    }

    public void setServerName(String serverName) {
        this.serverName = serverName;
    }

    public String getServerPort() {
        return serverPort;
    }

    public void setServerPort(String serverPort) {
        this.serverPort = serverPort;
    }

}

My question is, how do I change this class so that whenever some other component instantiates a new object of the class, the contents of the XML file will be available in the instance. 我的问题是,如何更改此类,以便每当其他组件实例化该类的新对象时,实例中都将提供XML文件的内容。 For example: 例如:

package com.digestersample;

import java.io.IOException;

import org.xml.sax.SAXException;

public class MyOtherClass {

    public static void main(String[] args) {

        MyConfig mc;
        try {

            mc = new MyConfig("/home/user/MyConfig.xml");

            System.out.println( mc.getServerName() );
            System.out.println( mc.getServerPort() );

        } catch (IOException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        }

    }

}

At the moment, the above instantiation causes a java.lang.InstantiationException. 目前,以上实例化导致java.lang.InstantiationException。

Thanks. 谢谢。

I realise this is not a direct answer to your question, but that is a hell of a lot of code for such a simple config, and your encountering problemns. 我意识到这不是您问题的直接答案,但是对于这么简单的配置以及您遇到的问题,这真是太多代码了。 As mentioned in your original post Simple XML http://simple.sourceforge.net does the job much better in my opinion. 正如您在原始文章中提到的,Simple XML http://simple.sourceforge.net在我看来做得更好。

@Root
public class MyConfig {

  @Element
  private String serverName;

  @Element
  private int serverPort

  public MyConfig() {
     super();
  }

  public MyConfig(File file) {
     Style style = new CamelCaseStyle();
     Persister persister = new Persister(style);

     persister.read(this, file);
  }

  public String getServerName() {
    return name;
  }

  public int getServerPort() {
    return port;
  }
}

And create it with. 并创建它。

MyConfig mc = new MyConfig("/home/user/MyConfig.xml");

System.out.println("Name: " + mc.getServerName());
System.out.println("Port: " + mc.getServerPort());

Done! 做完了! and you will see no exceptions. 您将不会看到任何例外。 Also, for your digester exception, you are missing the public no argument constructor similar to what I have added to the MyConfig example. 另外,对于摘要程序异常,您缺少公共的无参数构造函数,类似于我添加到MyConfig示例中的构造函数。

It has been a while since I looked at the commons digester, but I expect the InstantiationException is because the digester expects the MyConfig class to be a JavaBean . 自从我看了Commons摘要器以来已经有一段时间了,但是我希望InstantiationException是因为摘要器期望MyConfig类是JavaBean One of the defining characteristics of a JavaBean is that it has a public, zero-arg constructor . JavaBean的定义特征之一是它具有公共的,零参数的构造函数

You might think about using some other class to create your MyConfig instance: 您可能会考虑使用其他一些类来创建MyConfig实例:

public class MyConfigFactory

    public MyConfig createMyConfig(String configFile) throws IOException, SAXException
    {
        Digester digester = new Digester();
        digester.setValidating(false);

        digester.addObjectCreate("MyConfig", MyConfig.class);

        digester.addCallMethod("MyConfig/ServerName", "setServerName", 0);
        digester.addCallMethod("MyConfig/ServerPort", "setServerPort", 0);

        MyConfig mc = (MyConfig) digester.parse(new File(configFile));

        return mc;
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM