Path: csiph.com!aioe.org!.POSTED!not-for-mail From: =?UTF-8?Q?Arne_Vajh=c3=b8j?= Newsgroups: comp.lang.java.programmer Subject: Re: XML Date: Sat, 13 Aug 2016 15:38:03 -0400 Organization: Aioe.org NNTP Server Lines: 191 Message-ID: References: <34f5f605-db80-441c-9730-ceecf445c1a8@googlegroups.com> <0176078c-ab98-4e66-ba3e-b14ee88b58e0@googlegroups.com> <487a50aa-8e4b-460a-9824-bd23c26d4c02@googlegroups.com> <00fae8a8-dc01-435f-9f33-e5a5055d93df@googlegroups.com> NNTP-Posting-Host: 7SK6yTFfqwlIPNBLl3l7Qg.user.gioia.aioe.org Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit X-Complaints-To: abuse@aioe.org User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:45.0) Gecko/20100101 Thunderbird/45.2.0 X-Notice: Filtered by postfilter v. 0.8.2 Xref: csiph.com comp.lang.java.programmer:35309 On 8/10/2016 4:29 PM, Eric Douglas wrote: > Now, I'm not sure the best API to manage records. As the only method > I found for storing multiple records with JAXB is a List of the > DataRecord instances, how do I pass it a key value, get one or more > of these record objects, update a field (or fields), and write it > back out? This RMFID.xsd maps to an RMFID Java class which gives me > instances specific to this file name where I can call it's > setFILENAME(), getFILENAME() methods, but I don't see an obvious way > to get specific instances of the RMFID from the list aside from > customizing these classes further to map out what keys I need and > mapping them through the DataFile class. I'm wondering if it makes > sense to keep going down this path or try something else, like JiBX > which claims to do all this marshall/unmarshall stuff plus add code > to the Java classes to make everything more efficient and support > XPath queries to find records? Here is a complete example showing some stuff. First we have the data model: package jaxbdemo; public abstract class Data { private int iv; public Data() { this(0); } public Data(int iv) { super(); this.iv = iv; } public int getIv() { return iv; } public void setIv(int iv) { this.iv = iv; } } package jaxbdemo; public class DataA extends Data { private String sv; public DataA() { this(0, ""); } public DataA(int iv, String sv) { super(iv); this.sv = sv; } public String getSv() { return sv; } public void setSv(String sv) { this.sv = sv; } @Override public String toString() { return String.format("{ %d, %s }", getIv(), getSv()); } } package jaxbdemo; public class DataB extends Data { private double xv; public DataB() { this(0, 0.0); } public DataB(int iv, double xv) { super(iv); this.xv = xv; } public double getXv() { return xv; } public void setXv(double xv) { this.xv = xv; } @Override public String toString() { return String.format("{ %d, %f }", getIv(), getXv()); } } Completely standard. Now we create a wrapper class handling all of the JAXB: package jaxbdemo; import java.util.ArrayList; import java.util.List; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElements; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name="list") public class DataContainer { private List list; public DataContainer() { list = new ArrayList<>(); } @XmlElements( { @XmlElement(name="a", type=DataA.class), @XmlElement(name="b", type=DataB.class) } ) public List getList(){ return list; } } Now for usage. First setup: // JAXB JAXBContext jxbctx = JAXBContext.newInstance(DataContainer.class); Marshaller m = jxbctx.createMarshaller(); Unmarshaller um = jxbctx.createUnmarshaller(); Let us try write a file: DataContainer data = new DataContainer(); data.getList().add(new DataA(123, "ABC")); data.getList().add(new DataB(456, 123.456)); m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); try(OutputStream os = new FileOutputStream("/work/demo.xml")) { m.marshal(data, os); } demo.xml looks like: 123 ABC 456 123.456 which I consider to be "nice" XML. Reading the file again is simple: // load DataContainer data2 = null; try(InputStream is = new FileInputStream("/work/demo.xml")) { data2 = (DataContainer)um.unmarshal(is); } Searching for various data is easy using the new Java 8 streams: // search Data o1 = data2.getList().stream().filter(item -> item.getIv() == 456).findFirst().get(); Data o2 = data2.getList().stream().filter(item -> item instanceof DataA && ((DataA)item).getSv().equals("ABC")).findFirst().get(); Objects can be update: // update o1.setIv(789); ((DataA)o2).setSv("XXX"); And when written to another file: // save again try(OutputStream os = new FileOutputStream("/work/demo2.xml")) { m.marshal(data2, os); } then demo2.xml has the expected content: 123 XXX 789 123.456 Arne