不是Java新手;但是XML解析相对较新。我对那里的许多XML工具有一点了解,但对它们中的任何一个都没有多少。我也不是XML-pro。
我的特殊问题是这个...我得到了一个XML文档,我无法修改,只需要将它的随机位解析为Java对象。只要合理,纯粹的速度并不是很重要的因素。同样,内存占用也不一定是绝对最优的,只是不是疯了。我只需要通读文档一次就可以解析它,之后我会将它扔进bitbucket并使用我的POJO。
所以,我愿意接受建议......你会使用哪种工具?
而且,您是否会建议一些初学者代码来满足我的特殊需求?
这是一个示例XML片段以及我正在尝试制作的相关POJO:
<xml>
<item id="...">
...
</item>
<metadata>
<resources>
<resource>
<ittype>Service_Links</ittype>
<links>
<link>
<path>http://www.stackoverflow.com</path>
<description>Stack Overflow</description>
</link>
<link>
<path>http://www.google.com</path>
<description>Google</description>
</link>
</links>
</resource>
<resource>
<ittype>Article_Links</ittype>
<links>
...
</links>
</resource>
...
</resources>
</metadata>
</xml>
public class MyPojo {
@Attribute(name="id")
@Path("item")
public String id;
@ElementList(entry="link")
@Path("metadata/resources/resource/links")
public List<Link> links;
}
注意:这个问题最初由this question产生,我尝试使用SimpleXml解决它;我想到也许有人可以建议一条不同的路线去解决同样的问题。
另请注意:我真的希望有一个 CLEAN 解决方案...我的意思是,使用带有最少代码的注释和/或xpath ......我想要的最后一件事是巨大的类文件,有大量笨拙的方法...那,我已经......我正在努力寻找更好的方法。
:d
答案 0 :(得分:1)
好的,所以我找到了一个解决方案(对我来说)似乎以最合理的方式解决了我的需求。我对其他建议表示道歉,但我更喜欢这条路线,因为它将大部分解析规则作为注释,而我必须编写的程序代码很少。
我最终选择了JAXB;最初我认为JAXB要么从Java类创建XML,要么将XML解析为Java类,但只能使用XSD。然后我发现JAXB的注释可以将XML解析为没有XSD的Java类。
我正在使用的XML文件非常庞大且非常深入,但我只需要点到点就可以了;我担心将导航到未来的地方非常困难。所以我选择构建一个以XML格式建模的文件夹树...每个文件夹映射到一个元素,每个文件夹中都有一个表示该实际元素的POJO。
问题是,有时会有一个元素,它有一个子元素,有几个级别,它有一个我关心的属性。为每个属性创建4个嵌套文件夹和POJO只是为了访问单个属性会很麻烦。但这就是你用JAXB做的事情(至少,从我能说的);我又一次在角落里。
然后我偶然发现EclipseLink's JAXB-implementation: Moxy。 Moxy有一个@XPath注释,我可以放在那个父POJO中,并使用向下导航几个级别来访问单个属性,而无需创建所有这些文件夹和元素-POJO。好的。
所以我创建了这样的东西: (注意:我选择使用getter来处理需要按摩值的情况)
// maps to the root-"xml" element in the file
@XmlRootElement( name="xml" )
@XmlAccessorType( XmlAccessType.FIELD )
public class Xml {
// this is standard JAXB
@XmlElement;
private Item item;
public Item getItem() {
return this.item;
}
...
}
// maps to the "<xml><item>"-element in the file
public class Item {
// standard JAXB; maps to "<xml><item id="...">"
@XmlAttribute
private String id;
public String getId() {
return this.id;
}
// getting an attribute buried deep down
// MOXY; maps to "<xml><item><rating average="...">"
@XmlPath( "rating/@average" )
private Double averageRating;
public Double getAverageRating() {
return this.average;
}
// getting a list buried deep down
// MOXY; maps to "<xml><item><service><identification><aliases><alias.../><alias.../>"
@XmlPath( "service/identification/aliases/alias/text()" )
private List<String> aliases;
public List<String> getAliases() {
return this.aliases;
}
// using a getter to massage the value
@XmlElement(name="dateforindex")
private String dateForIndex;
public Date getDateForIndex() {
// logic to parse the string-value into a Date
}
}
另请注意,我采用了将XML对象与我在应用程序中实际使用的模型对象分开的路径。因此,我有一个工厂将这些原始对象转换为更强大的对象,我实际上在我的应用程序中使用它。
答案 1 :(得分:0)
如果您的XML文档相对较小(如此处所示),我将使用DOM框架和XPath类。以下是我的一个教程中的一些boilerplate DOM/XPath code:
File xmlFile = ...
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(xmlFile);
XPath xp = XPathFactory.newInstance().newXPath();
String value = xp.evaluate("/path/to/element/text()", doc);
// .. reuse xp to get other values as required
换句话说,基本上你:
通过DocumentBuilder将您的XML转换为Document对象;
创建一个XPath对象;
重复调用XPath.evaluate(),传入所需元素的路径 和你的文件。
如你所见,抓住你的Document对象并且像所有优秀的XML API一样,有一点点狡猾,它引发了大量愚蠢无意义的检查异常。但除此之外,解析结构相对固定的简单的中小型XML文档是相当没有意义的。
答案 2 :(得分:0)
您可以使用SAXParser或STAXParser。如果你能负担得起更多的内存,那么你也可以使用DOMParser。我建议STAXParser最适合你。