【问题标题】:Good way to parse XML like this sample?像这个示例那样解析 XML 的好方法?
【发布时间】:2012-05-22 08:20:10
【问题描述】:

我想知道像这样解析 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 元素时,我可以例如创建一个新实例,例如一个邮件类,我对此没有任何问题。但是:如果我来怎么办?到一个到元素?我怎么知道它是否真的在 MailNotification 元素内,而不是在根的正下方?换句话说:我缺少的是处理“现在我在 MailNotification”元素等状态的最佳实践。

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

感谢任何提示!

【问题讨论】:

    标签: java xml


    【解决方案1】:

    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;
    }
    

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

    【讨论】:

    • 非常感谢,我不知何故不同意它 - 在主 while 循环中使用第二个(第三个,第四个 ...)while 循环是有意义的。适合我的情况的完美答复。感谢所有其他人,链接中有一些有趣的东西。但现在 Stax 可以胜任。
    • +1 因为它非常短、轻量级、在流模式下工作,正是我目前正在寻找的。​​span>
    【解决方案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;
      }
    

    【讨论】:

    • 我实际上最终使用了 Digester,使用起来非常简单。谢谢你的好提示!由于白羊座的回答仍然更接近我最初的问题,我会将他的问题作为正确的问题,尽管你的问题最终对我更有帮助;-) [但这不是我在我的原始问题的 100% 的答案意见]
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

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

      XML response how to assign values to variables

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

      至于你的问题很少有类似的,即:

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

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

      【讨论】:

        【解决方案5】:

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

        有很多这样的,请参阅this question 进行比较。我自己用过jdom,它很容易使用,也很容易理解我最看重的东西。但是,现在有更高级的替代方案。

        【讨论】:

          【解决方案6】:

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

          我可能会使用 JDOM。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-09-20
            • 2012-09-08
            • 2016-09-27
            • 2015-12-08
            • 2014-07-13
            • 2013-02-17
            • 2014-07-10
            • 1970-01-01
            相关资源
            最近更新 更多