我想解组下面的XML并从中仅提取CD
元素的列表:
<?xml version="1.0" encoding="UTF-8"?>
<Root>
<Header>
<SomData>
<Name>Name</Name>
</SomData>
</Header>
<Message>
<DziubasekInfo>
<some_data>Data</some_data>
</DziubasekInfo>
<CATALOG>
<Entry>
<CD>
<TITLE>Empire Burlesque</TITLE>
<ARTIST>Bob Dylan</ARTIST>
<COUNTRY>USA</COUNTRY>
<COMPANY>Columbia</COMPANY>
<PRICE>10.90</PRICE>
<YEAR>1985</YEAR>
</CD>
</Entry>
<Entry>
<CD>
<TITLE>Hide your heart</TITLE>
<ARTIST>Bonnie Tyler</ARTIST>
<COUNTRY>UK</COUNTRY>
<COMPANY>CBS Records</COMPANY>
<PRICE>9.90</PRICE>
<YEAR>1988</YEAR>
</CD>
</Entry>
<Entry>
<CD>
<TITLE>Greatest Hits</TITLE>
<ARTIST>Dolly Parton</ARTIST>
<COUNTRY>USA</COUNTRY>
<COMPANY>RCA</COMPANY>
<PRICE>9.90</PRICE>
<YEAR>1982</YEAR>
</CD>
</Entry>
</CATALOG>
</Message>
</Root>
这是我的实际代码:
@XmlRootElement(name="CATALOG")
@XmlAccessorType(XmlAccessType.FIELD)
public class Catalog {
@XmlElement(name = "Entry", type = Entry.class)
private List<Entry> list = new ArrayList<>();
.... getters, setters
}
@XmlType(name="Entry")
@XmlAccessorType(XmlAccessType.FIELD)
public class Entry {
@XmlElement(name = "CD", type = Cd.class)
private List<Cd> cdList = new ArrayList<>();
... getters, setters
}
@XmlType(name="CD")
@XmlAccessorType(XmlAccessType.FIELD)
public class Cd {
@XmlElement(name="TITLE")
private String title;
@XmlElement(name="ARTIST")
private String artist;
@XmlElement(name="PRICE")
private String price;
.... getters, setters
}
InputStream inp = getClass().getResourceAsStream("cd_catalog.xml");
XMLInputFactory xif = XMLInputFactory.newFactory();
StreamSource source = new StreamSource(inp);
XMLStreamReader xsr = xif.createXMLStreamReader(source);
while (!(xsr.isStartElement() && "CATALOG".equals(xsr.getLocalName()))) {
xsr.next();
}
JAXBContext jc = JAXBContext.newInstance(Catalog.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
Catalog catalog = unmarshaller.unmarshal(xsr, Catalog.class).getValue();
System.out.println("Entries = " + catalog.getList().size());
for (Entry e : catalog.getList()) {
System.out.format("CD: %20s / %30s / %10s\n",
e.getCdList().get(0).getArtist(),
e.getCdList().get(0).getTitle(),
e.getCdList().get(0).getPrice());
}
xsr.close();
正如您所看到的,这里有3个类:Catalog
包裹Entry
,后者又包裹Cd
类。
实际上,每个Entry
只包含一个Cd
条目。
有没有办法消除这个包装类之一,只使用2个类而不是3个?
并且为了简化这段代码,特别是这个片段看起来有点尴尬:
e.getCdList().get(0).getArtist(),
e.getCdList().get(0).getTitle(),
e.getCdList().get(0).getPrice()
拥有一个只包含一个项目的列表并且总是只获得这个条目有点愚蠢,最好这样做:
e.getCdList().getArtist(), e.getCdList().getTitle(), e.getCdList().getPrice()
答案 0 :(得分:0)
任何与XML相关的映射的基本点不是代码,而是XML。(实际上是XML Schema)。您的JAXB注释定义了架构。所以,如果你的XML有架构 就像你展示:
<CATALOG>
<Entry>
<CD>
<TITLE>Empire Burlesque</TITLE>
<ARTIST>Bob Dylan</ARTIST>
<COUNTRY>USA</COUNTRY>
<COMPANY>Columbia</COMPANY>
<PRICE>10.90</PRICE>
<YEAR>1985</YEAR>
</CD>
</Entry>
...
那就是它的本质。 Entry元素有CD元素。 如果您想要消除CD元素,您的XML必须如下所示:
<CATALOG>
<Entry>
<TITLE>Empire Burlesque</TITLE>
<ARTIST>Bob Dylan</ARTIST>
<COUNTRY>USA</COUNTRY>
<COMPANY>Columbia</COMPANY>
<PRICE>10.90</PRICE>
<YEAR>1985</YEAR>
</Entry>
不多也不少...... Java对象(使用JAXB注释)只是XML模式所指示的反映。如果你不能改变XML - 你必须忍受它。
BTW:我很确定Entry可能不含CD元素,如DVD,TAPE,VINIL等...
答案 1 :(得分:0)
我终于使用EclipseLink / Moxy和@XmlPath(value="Entry/CD")
注释解决了这个问题。
Cd
类与问题中的相同。
这是Catalog
类:
@XmlRootElement(name="CATALOG")
@XmlAccessorType(XmlAccessType.FIELD)
public class Catalog {
@XmlElement(name = "CD", type = Cd.class)
@XmlPath(value="Entry/CD")
private List<Cd> list = new ArrayList<>();
... getters/setters
}
以下是代码:
System.setProperty("javax.xml.bind.context.factory","org.eclipse.persistence.jaxb.JAXBContextFactory");
InputStream inp = getClass().getResourceAsStream("cd_catalog.xml");
assertTrue(inp != null);
XMLInputFactory xif = XMLInputFactory.newFactory();
StreamSource source = new StreamSource(inp);
XMLStreamReader xsr = xif.createXMLStreamReader(source);
while (!(xsr.isStartElement() && "CATALOG".equals(xsr.getLocalName()))) {
xsr.next();
}
JAXBContext jc = JAXBContext.newInstance(Catalog.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
Catalog catalog = unmarshaller.unmarshal(xsr, Catalog.class).getValue();
System.out.println("Entries = " + catalog.getList().size());
for (Cd e : catalog.getList()) {
System.out.format("CD: %20s / %30s / %10s\n", e.getArtist(), e.getTitle(), e.getPrice());
}
xsr.close();