对Java来说不是新手;但对于XML解析而言相对较新。我对其中的许多XML工具了解甚少,但对其中任何一个工具了解都不多。我也不是XML专业人士。
我的特殊问题是…我得到了一个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; }
另请注意:我真的很希望有一个 _CLEAN_解决方案…我的意思是说,使用批注和/或xpath使用最少的代码…我想要的最后一件事是具有庞大笨拙方法的庞大类文件。那,我已经有…我正在尝试寻找一种更好的方法。
好的,所以我选择了一个解决方案,该解决方案(对我而言)似乎以最合理的方式满足了我的需求。我对其他建议表示歉意,但我更喜欢这条路线,因为它保留了大多数解析规则作为注释,而我必须编写的很少的过程代码非常少。
我最终选择了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对象与我在应用程序中实际使用的模型对象分离的方法。因此,我有一家工厂将这些粗略的对象转换为实际上在我的应用程序中使用的更坚固的对象。