JAXB过滤了解析 [英] JAXB filtered parsing
问题描述
我正在使用JAXB来解析基于GWT的应用程序中的XML文件。 XML看起来像这样(简化示例):
I'm using JAXB to parse an XML file in my GWT based application. The XML looks like this (a simplified example):
<addressbook>
<company name="abc">
<contact>
<name>...</name>
<address>...</address>
</contact>
<contact>
<name>...</name>
<address>...</address>
</contact>
<contact>
<name>...</name>
<address>...</address>
</contact>
...
...
</company>
<company name="def">
<contact>
<name>...</name>
<address>...</address>
</contact>
...
...
</company>
...
...
</addressbook>
我已经定义了如下所示的类:
I've defined the classes as shown below:
@XmlRootElement(name="addressbook")
public class Addressbook implements Serializable {
private ArrayList<Company> companyList = new ArrayList<Company>();
public Addressbook() {
}
@XmlElement(name = "company")
public ArrayList<Company> getCompanyList() {
return companyList;
}
}
=============================
@XmlRootElement(name="company")
public class Company implements Serializable {
private String name;
private ArrayList<Contact> contactList = new ArrayList<Contact>();
public Company() {
}
@XmlAttribute
public String getName() {
return name;
}
@XmlElement(name = "contact")
public ArrayList<Contact> 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文件,然后手动过滤记录。但是如果输入文件很大,那么解析我需要的东西可能会更有效。那么是否可以预先指定一个标准并仅解析特定记录?
I need to get the list of contacts based on the company name. For example, get all contacts for company "abc". I can parse the entire XML file and then manually filter the records. But if the input file is big, it might be more efficient to parse only what I need. So is it possible to specify a criterion upfront and parse only specific records?
谢谢。
推荐答案
您可以在 EclipseLink JAXB(MOXy )来处理这种情况(我是MOXy技术主管):
You could use the @XmlPath extension in EclipseLink JAXB (MOXy) to handle this case (I'm the MOXy tech lead):
@XmlRootElement(name="addressbook")
public class Addressbook implements Serializable {
private ArrayList<Company> companyList = new ArrayList<Company>();
public Addressbook() {
}
@XmlPath("company[@name='abc']")
public ArrayList<Company> getCompanyList() {
return companyList;
}
}
更多信息:
- http://bdoughan.blogspot.com/2011/03/map-to-element-based-on-attribute-value.html
更新 - 使用StreamFilter
以下示例演示了如何在此用例中使用StreamFilter:
The example below demonstrates how a StreamFilter could be leveraged for this use case:
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的实现如下:
The implementation of the StreamFilter is as follows:
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;
}
}
这篇关于JAXB过滤了解析的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!