有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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>

我使用的是Java7,完整的XML更长,但它不是真正的大文件。我考虑使用Stax Pull解析器,因为它看起来很简单,但有一件事我不确定它是否真的是一种好方法:

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

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

谢谢你的提示


共 (6) 个答案

  1. # 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;
    }
    

    (*)为了澄清“最佳选择”,这取决于你想做什么
    ^如果XML直接映射到要创建的对象,{a1}非常好
    ^如果您想以复杂的方式导航XML,{a2}很有用,例如,如果您实现了XPath之类的东西;但对于简单的语法分析来说,它有点过头了。这是消耗大部分内存的方法
    ^在StAX出现之前,{a3}是最轻、最高效的解析器

  2. # 2 楼答案

    您可以使用任何像样的XML解析库来解析它。然后,“收件人”将包含在“邮件通知”对象中

    有很多这样的例子,请参见this question进行比较。我自己也用过jdom,它很容易使用,也很容易理解我非常重视它。然而,现在有更先进的替代品

  3. # 3 楼答案

    询问使用什么工具来解析XML似乎有点像询问您使用什么编程语言:您会得到回答说“StAX是最好的”或“JAXB是最好的”,而没有给出任何理由说明它们比其他方法有什么好处。老实说,在不了解更多项目的需求和约束条件的情况下,客观地回答这个问题是不可能的,但对于绝大多数项目来说,使用任何流行的技术,任务都非常简单,不值得浪费时间为决策而烦恼

    我可能会使用JDOM

  4. # 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. # 5 楼答案

    使用JAXB怎么样?你可以有一个带有注释的java类,只需要对其进行marshall或unmarshall处理,这非常简单

  6. # 6 楼答案

    看看消化器

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