像这样的样本解析XML的好方法?

时间:2012-05-14 20:05:20

标签: java xml

我想知道解析XML的最佳做法是什么:

<root>
    <MailNotification enable="true">
        <To>foo@bar.org</To>
        <From>foo@bar.org</From>
        <Server>smtp.bar.org</Server>
        <Port>465</Port>
        <Username>foo@bar.org</Username>
        <Password>fooo!</Password>
    </MailNotification>
</root>

我使用的是Java 7,完整的XML更长,但它并不是一个非常大的文件。我想过使用Stax Pull Parser,因为它看似简单,但有一点我不确定它是否真的是一个好方法:

当来到 MailNotification元素时,我可以例如创建一个新的例子邮件类,我没有问题。但是:如果我来,例如到 To元素?我怎么知道它是否真的在MailNotification元素内,而不是直接在根目录下?换句话说:我缺少的是处理诸如“现在我在MailNotification”元素中的状态的最佳实践。

注意:我知道我可以先验证XML,但想象一下,允许在 MailNotification元素 To元素中包含 To元素 作为另一个语义上不同的元素的孩子 - 同样的问题:我不知何故需要跟踪状态/上下文以确保我正确地解释 To元素

感谢任何提示!

6 个答案:

答案 0 :(得分:4)

StAX Stream Reader是最好的*选择。只需使用Java堆栈来保持状态,就像在这个例子中一样。常量为XMLStreamConstants

XMLStreamReader reader;

void parseRoot() {
    reader.require(START_ELEMENT, null, "root");

    while (reader.nextTag() == START_ELEMENT) {
        switch (reader.getLocalName()) {
        case "MailNotification":
            MailNotification mail = parseMail();
            // do something with mail
            break;
        // more cases
        }
    }

    reader.require(END_ELEMENT, null, "root");
}

MailNotification parseMail() {
    reader.require(START_ELEMENT, null, "MailNotification");
    MailNotification mail = new MailNotification();

    while (reader.nextTag() == START_ELEMENT) {
        switch (reader.getLocalName()) {
        case "To":
            mail.setTo(parseString());
            break;
        // more cases
        }
    }

    reader.require(END_ELEMENT, null, "MailNotification");
    return mail;
}

String parseString() {
    String text = "";
    if (reader.next() == CHARACTERS) {
        text = reader.getText();
        reader.next();
    }
    return text;
}

(*)只是为了澄清“最佳选择”,这取决于你想做什么 如果您的XML直接映射到您要创建的对象,则JAXB非常好 如果您想以复杂的方式浏览XML,JDOM非常有用,例如,如果您实现XPath之类的东西;但对于简单的解析它的矫枉过正。这是消耗大部分内存的方法 在StAX出现之前,SAX是最轻,最有效的解析器。

答案 1 :(得分:2)

看看Digester。

public static final String TEST_XML = "<root>\n" +
          "<MailNotification>\n" +
          " <to>foo@bar.org</to>\n" +
          " <from>foo@bar.org</from>\n" +
          " </MailNotification>\n" +
          "</root>";



Digester digester = new Digester();
digester.setValidating(false);

digester.addObjectCreate("root/MailNotification", MailNotification.class);
digester.addBeanPropertySetter("root/MailNotification/to", "to");
digester.addBeanPropertySetter("root/MailNotification/from", "from");

MailNotification notification = (MailNotification) digester.parse(new StringReader(TEST_XML));
System.out.println(notification.getTo());
System.out.println(notification.getFrom());



public class MailNotification {
  private String to;
  private String from;

  public String getTo() {
    return to;
  }

  public void setTo(String to) {
    this.to = to;
  }

  public String getFrom() {
    return from;
  }

  public void setFrom(String from) {
    this.from = from;
  }

答案 2 :(得分:1)

如何使用JAXB?你可以拥有一个带注释的java类,只需要编组或取消编组即可。

答案 3 :(得分:0)

你可以看看我以前的答案:

XML response how to assign values to variables

我确信在SO上有很多相同/相似的答案。

关于你的几个相似的问题,即:

How do I know if it is really inside a MailNotification element and not directly below the root?

你有启动元素/结束元素。

答案 4 :(得分:0)

你要用任何体面的XML解析库解析它。然后“To”将包含在“MailNotification”对象中。

有大量此类内容,请参阅this question进行比较。我自己使用过jdom,它很容易使用并且理解我非常重视的东西。但是,如今还有更先进的替代品。

答案 5 :(得分:0)

询问用什么工具来解析XML似乎有点像问你使用什么编程语言:你会得到答案说“StAX是最好的”或“JAXB是最好的”,而没有给出任何理由来说明他们提供的优惠其他方法。说实话,如果不了解项目的要求和限制,就不可能客观地回答这个问题,但是对于绝大多数项目来说,任务使用任何流行的技术都是非常容易的,因此不值得浪费时间。决定。

我可能会使用JDOM。