JAXB过滤了解析

我正在使用JAXB来解析基于GWT的应用程序中的XML文件。 XML看起来像这样(一个简化的例子):

   ... 
...
...
...
...
...
... ... ...
...
... ... ... ...

我已经定义了类,如下所示:

 @XmlRootElement(name="addressbook") public class Addressbook implements Serializable { private ArrayList companyList = new ArrayList(); public Addressbook() { } @XmlElement(name = "company") public ArrayList getCompanyList() { return companyList; } } ============================= @XmlRootElement(name="company") public class Company implements Serializable { private String name; private ArrayList contactList = new ArrayList(); public Company() { } @XmlAttribute public String getName() { return name; } @XmlElement(name = "contact") public ArrayList getContactList() { return contactList; } ... ... } ============================= @XmlRootElement(name="contact") public class Contact implements Serializable { private String name; private String address; public Contact() { } @XmlElement public String getName () { return name; } @XmlElement public String getAddress () { return address; } ... ... } 

这是代码:

 try { JAXBContext jc = JAXBContext.newInstance(Addressbook.class); Unmarshaller um = jc.createUnmarshaller(); addressbook = (Addressbook) um.unmarshal(new FileReader("ds/addressbook.xml")); } catch (JAXBException e) { e.printStackTrace(); } 

我需要根据公司名称获取联系人列表。 例如,获取公司“abc”的所有联系人。 我可以解析整个XML文件,然后手动过滤记录。 但是如果输入文件很大,那么解析我需要的东西可能更有效。 那么是否可以预先指定一个标准并仅解析特定记录?

谢谢。

您可以使用EclipseLink JAXB(MOXy )中的@XmlPath扩展来处理这种情况(我是MOXy技术主管):

 @XmlRootElement(name="addressbook") public class Addressbook implements Serializable { private ArrayList companyList = new ArrayList(); public Addressbook() { } @XmlPath("company[@name='abc']") public ArrayList getCompanyList() { return companyList; } } 

了解更多信息:


更新 – 使用StreamFilter

下面的示例演示了如何在此用例中使用StreamFilter:

 import java.io.FileInputStream; import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamReader; public class Demo { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(Addressbook.class); XMLInputFactory xif = XMLInputFactory.newFactory(); FileInputStream xmlStream = new FileInputStream("input.xml"); XMLStreamReader xsr = xif.createXMLStreamReader(xmlStream); xsr = xif.createFilteredReader(xsr, new CompanyFilter()); Unmarshaller unmarshaller = jc.createUnmarshaller(); Addressbook addressbook = (Addressbook) unmarshaller.unmarshal(xsr); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(addressbook, System.out); } } 

StreamFilter的实现如下:

 import javax.xml.stream.StreamFilter; import javax.xml.stream.XMLStreamReader; public class CompanyFilter implements StreamFilter { private boolean accept = true; public boolean accept(XMLStreamReader reader) { if(reader.isStartElement() && "company".equals(reader.getLocalName())) { accept = "abc".equals(reader.getAttributeValue(null, "name")); } else if(reader.isEndElement()) { boolean returnValue = accept; accept = true; return returnValue; } return accept; } } 

你可以

  • 将XSLT转换应用于XML文件,或
  • 将文件解组为DOM,并使用XPath选择所需的节点

在将生成的对象传递给unmarshal方法之前

但是,创建一个由公司名称键入的内存Map可能更简单:

 public class SearchableAddressBook { public final Map companyMap = new HashMap(); public SearchableAddressBook(List companyList) { for (Company company: companyList) { companyMap.add(company.getName(), company)); } } 

或者如果你真的想要过度设计它,可以创建一个内存数据库。