JAXB filtered parsing

后端 未结 2 1434
执笔经年
执笔经年 2020-12-02 00:25

I\'m using JAXB to parse an XML file in my GWT based application. The XML looks like this (a simplified example):



    

        
相关标签:
2条回答
  • 2020-12-02 00:25

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

    For More Information:

    • http://bdoughan.blogspot.com/2011/03/map-to-element-based-on-attribute-value.html

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

    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;
        }
    
    }
    
    0 讨论(0)
  • 2020-12-02 00:52

    You could either

    • Apply an XSLT transformation to the XML file, or
    • Unmarshall the file into a DOM, and use XPath to select the nodes you want

    before passing the resulting object(s) to the unmarshal method

    It might be simpler though, to create an in-memory Map keyed by company name:

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

    Or create an in-memory DB if you really want over-engineer it.

    0 讨论(0)
提交回复
热议问题