像这个示例那样解析 XML 的好方法?
Posted
技术标签:
【中文标题】像这个示例那样解析 XML 的好方法?【英文标题】:Good way to parse XML like this sample? 【发布时间】: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 元素。
感谢任何提示!
【问题讨论】:
【参考方案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。
【讨论】:
以上是关于像这个示例那样解析 XML 的好方法?的主要内容,如果未能解决你的问题,请参考以下文章
传递给 CreateProcess 的参数没有像我预期的那样被解析