3

我想知道像这样解析 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 元素作为另一个语义不同元素的子元素 - 同样的问题:我需要以某种方式跟踪状态/ context 以确保我正确解释To 元素

感谢您的任何提示!

4

6 回答 6

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是最轻量级和最高效的解析器。

于 2012-05-14T20:24:24.297 回答
2

看看消化器。

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;
  }
于 2012-05-14T20:32:59.593 回答
1

使用JAXB怎么样?您可以拥有一个带有注释的 java 类,并且只需要编组或解组,这很容易。

于 2012-05-14T20:47:10.177 回答
0

你可以看看我之前的回答:

XML响应如何为变量赋值

而且我敢肯定这里有很多相同/相似的答案。

至于您在几个类似的问题中的问题,即:

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

你有开始元素/结束元素。

于 2012-05-14T20:26:08.337 回答
0

您可以使用任何体面的 XML 解析库来解析它。然后“收件人”将包含在“MailNotification”对象中。

有很多这样的,请参阅this question进行比较。我自己使用过jdom,它易于使用并且理解我非常看重的东西。但是,如今有更高级的替代方案。

于 2012-05-14T20:28:01.447 回答
0

询问使用什么工具来解析 XML 似乎有点像询问您使用什么编程语言:您将得到“StAX 是最好的”或“JAXB 是最好的”这样的答案,而没有给出任何理由说明它们比其他方法提供了什么好处。老实说,如果不进一步了解项目的要求和约束,就不可能客观地回答这个问题,但是对于绝大多数项目来说,使用任何流行的技术都可以轻松完成任务,因此不值得浪费时间担心决定。

我可能会使用 JDOM。

于 2012-05-14T22:22:14.930 回答