好的,所以我选择了一个解决方案,该解决方案(对我而言)似乎以最合理的方式满足了我的需求。我对其他建议表示歉意,但我更喜欢这条路线,因为它保留了大多数解析规则作为注释,而我必须编写的很少的过程代码非常少。
我最终选择了JAXB。最初,我认为JAXB要么从java类创建XML,要么将XML解析为java类,但仅使用XSD。然后,我发现JAXB具有注释,可以在没有XSD的情况下将XML解析为java类。
我正在使用的XML文件很大而且很深,但是我只需要在这里和那里一点一滴。我担心将来很难导航到什么地图。因此,我选择构建一个以XML建模的文件夹树…每个文件夹映射到一个元素,并且每个文件夹中都有一个POJO表示该实际元素。
问题是,有时某个元素的子元素在多个级别下具有我关心的单个属性。创建4个嵌套文件夹和每个POJO只是为了访问单个属性会很痛苦。但这就是您使用JAXB的方式(至少,据我所知);我又一次陷入了困境。
然后我偶然发现了EclipseLink的JAXB实现:Moxy。Moxy有一个@XPath批注,我可以将其放置在该父POJO中,并用于向下浏览多个级别以访问单个属性,而无需创建所有这些文件夹和element- POJO。真好
因此,我创建了这样的内容:(注意:在需要按摩值的情况下,我选择使用吸气剂)
// 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对象与我在应用程序中实际使用的模型对象分离的方法。因此,我有一家工厂将这些粗略的对象转换为实际上在我的应用程序中使用的更坚固的对象。