Java JAXB过滤解析

Java JAXB过滤解析,java,xml,jaxb,Java,Xml,Jaxb,我在基于GWT的应用程序中使用JAXB解析XML文件。XML如下所示(一个简化的示例): 我需要根据公司名称获取联系人列表。例如,获取公司“abc”的所有联系人。我可以解析整个XML文件,然后手动过滤记录。但是如果输入文件很大,只解析我需要的东西可能会更有效。那么,是否有可能预先指定一个条件并只解析特定的记录呢 谢谢 你也可以 将XSLT转换应用于XML文件,或 将文件解组到DOM中,并使用XPath选择所需的节点 在将结果对象传递给解组方法之前 不过,创建由公司名称键入的内存映射可能更简单

我在基于GWT的应用程序中使用JAXB解析XML文件。XML如下所示(一个简化的示例):

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

谢谢

你也可以

  • 将XSLT转换应用于XML文件,或
  • 将文件解组到DOM中,并使用XPath选择所需的节点
在将结果对象传递给解组方法之前

不过,创建由公司名称键入的内存
映射可能更简单:

public class SearchableAddressBook {

    public final Map<String, Company> companyMap = new HashMap<String,Company>();

    public SearchableAddressBook(List<Company> companyList) {
        for (Company company: companyList) {
            companyMap.add(company.getName(), company));
        }

}
公共类SearchableAddressBook{
public final Map companyMap=new HashMap();
公共可搜索通讯簿(列出公司列表){
for(公司名称:companyList){
companyMap.add(company.getName(),company));
}
}

如果您真的想对内存数据库进行过度设计,也可以创建内存数据库。

您可以使用中的@XmlPath扩展来处理这种情况(我是MOXy技术负责人):

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;
    }

}

谢谢你的回复。你能给我看一下(或指给我看)吗使用这些方法中较简单的方法的示例代码?抱歉,我对这方面还是新手。更新了我的答案,尽管Map方法仍然解析整个XML文件,因此它可能不是您想要的。请记住测量各种数据集上的性能!您是否建议通过修改我的Addressbook类,解组将我应该把数据放到一个映射中去(实际上那太好了)?或者我应该创建一个新的类SearchableAddressBook来将列表转换成一个映射“after”解组?谢谢。不,恐怕你必须先解组,然后再添加到新的SearchableAddressBook中。我认为另一个答案可能更合适:-)巧合的是,当你发布回复时,我正在阅读你的博客以获取想法。我想这是我正在寻找的,但我真的希望避免为此而增加额外的库如果有可能的话。否则,我会考虑使用MOXY。在另一个注释中,不是将列表中的公司对象解压缩,我可以将它们作为映射吗?@ DFB-您可以将公司对象解封到映射()中。如果可能的话,可以使用StreamFilter来获得您想要的行为。(,使用标准JAXB API。感谢您的回复。我将研究StreamFilter。关于解组地图,我必须承认,我无法从您的博客文章中找到它。我想在我开始发布问题之前,我还有很多东西要学:)@DFB我提供了指向映射示例的错误链接。正确的链接是:@DFB-我已使用StreamFilter示例更新了我的答案,该示例应适用于任何JAXB实现。
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();
}
public class SearchableAddressBook {

    public final Map<String, Company> companyMap = new HashMap<String,Company>();

    public SearchableAddressBook(List<Company> companyList) {
        for (Company company: companyList) {
            companyMap.add(company.getName(), company));
        }

}
@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;
    }


}
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);
    }
}
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;
    }

}